Help us shape the future of Go! Take the 2026 Go Developer Survey

sqlite

package
v0.46.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 26, 2026 License: MIT Imports: 19 Imported by: 0

Documentation

Overview

Package sqlite is the SQLite DB driver. Uses modernc.org/sqlite (pure Go, CGO_ENABLED=0).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewMySQLStore

func NewMySQLStore(sqlDB *sql.DB) db.Store

NewMySQLStore returns the same Store in MySQL/MariaDB mode. The MySQL driver reuses this implementation — the placeholder syntax is identical and the column names are the same — and this flag covers the one construct where the two dialects genuinely disagree. See upsert.

func UpsertForMySQL

func UpsertForMySQL(q string) string

UpsertForMySQL is the rewrite upsert applies in MySQL mode, exported so the cross-engine gate in backend/internal/db can prepare every statement in this file exactly as a MySQL server receives it.

Types

type Driver

type Driver struct{}

Driver implements db.Driver.

func (Driver) Dialect

func (Driver) Dialect() string

Dialect returns the goose-compatible dialect name.

func (Driver) MigrationsFS

func (Driver) MigrationsFS() embed.FS

MigrationsFS returns the embedded SQLite migrations.

func (Driver) Name

func (Driver) Name() string

Name implements db.Driver.

func (Driver) NewStore

func (Driver) NewStore(sqlDB *sql.DB) db.Store

NewStore returns a Store backed by the given *sql.DB.

func (Driver) Open

func (Driver) Open(_ context.Context, dsn string) (*sql.DB, error)

Open returns a configured *sql.DB.

Default DSN tweaks: WAL mode, busy timeout 5s, foreign keys on.

type Store

type Store struct {

	// The catalogue_folders methods (internal/db catalogue_folders_sql.go).
	*db.CatalogueFolderSQL
	// SetStorageOrder (internal/db storage_order_sql.go).
	*db.StorageOrderSQL
	// contains filtered or unexported fields
}

Store implements db.Store atop SQLite — and, through the MySQL driver, atop MySQL/MariaDB as well.

func (*Store) AbortUnfinishedSyncRuns

func (s *Store) AbortUnfinishedSyncRuns(ctx context.Context, errMsg string) (int64, error)

func (*Store) ActivateTotp

func (s *Store) ActivateTotp(ctx context.Context, id int64) error

ActivateTotp moves the pending secret into totp_secret and flips the totp_enabled flag on.

func (*Store) AggNodes

func (s *Store) AggNodes(ctx context.Context, storageID int64) ([]db.NodeAgg, error)

func (*Store) AllNodesForIndex

func (s *Store) AllNodesForIndex(ctx context.Context) ([]*model.Node, error)

AllNodesForIndex returns every non-deleted node for the search rebuild job.

func (*Store) AttachStagedUploadTarget

func (s *Store) AttachStagedUploadTarget(ctx context.Context, id string, nodeID, opID int64) error

func (*Store) ClaimAppPluginScheduleItem

func (s *Store) ClaimAppPluginScheduleItem(ctx context.Context, pluginID int64, key, owner string, now time.Time) (bool, error)

ClaimAppPluginScheduleItem is the lease: one conditional UPDATE, true only for the process whose UPDATE actually moved the row out of `due`.

func (*Store) ClearTotp

func (s *Store) ClearTotp(ctx context.Context, id int64) error

ClearTotp wipes all 2FA state.

func (*Store) Close

func (s *Store) Close() error

Close implements db.Store.

func (*Store) CountActiveSessions

func (s *Store) CountActiveSessions(ctx context.Context) (int64, error)

CountActiveSessions returns the count of unexpired sessions.

func (*Store) CountLiveNodesUnder

func (s *Store) CountLiveNodesUnder(ctx context.Context, storageID int64, dir string) (int64, error)

func (*Store) CountNodesAddedSince

func (s *Store) CountNodesAddedSince(ctx context.Context, storageID int64, since time.Time) (int64, error)

CountNodesAddedSince counts non-deleted nodes created in the given window.

func (*Store) CountNodesByStorage

func (s *Store) CountNodesByStorage(ctx context.Context, storageID int64) (int64, error)

func (*Store) CountNodesDeletedSince

func (s *Store) CountNodesDeletedSince(ctx context.Context, storageID int64, since time.Time) (int64, error)

CountNodesDeletedSince counts soft-deleted nodes in the given window.

func (*Store) CountQueueDepth

func (s *Store) CountQueueDepth(ctx context.Context) (int64, error)

CountQueueDepth returns the number of running sync_runs (a stand-in "queue depth" until we ship a real op queue table).

func (*Store) CountRecentlyResolvedReplicaFailures

func (s *Store) CountRecentlyResolvedReplicaFailures(ctx context.Context, since time.Time) (int64, error)

CountRecentlyResolvedReplicaFailures returns the number of rows whose resolved_at is more recent than `since`. Used by the cron status report's "repaired_count" metric.

func (*Store) CountSyncConflictsByRun

func (s *Store) CountSyncConflictsByRun(ctx context.Context, runID int64) (int64, error)

CountSyncConflictsByRun returns the count of conflicts attributed to a run via timestamp window. We don't store run_id on conflicts (it's not in the schema), so we approximate by detected_at proximity.

func (*Store) CountTotalShares

func (s *Store) CountTotalShares(ctx context.Context) (int64, error)

CountTotalShares returns the number of currently-active shares.

func (*Store) CountTrashedExpired

func (s *Store) CountTrashedExpired(ctx context.Context, before time.Time) (map[int64]db.TrashTally, error)

CountTrashedExpired tallies per storage what ListTrashedExpired walks for the same cutoff. One grouped read over the partial deleted_at index.

func (*Store) CountUnresolvedReplicaFailures

func (s *Store) CountUnresolvedReplicaFailures(ctx context.Context) (int64, error)

CountUnresolvedReplicaFailures returns the unresolved count directly — cheaper than List for the dashboard counter.

func (*Store) CountUsers

func (s *Store) CountUsers(ctx context.Context) (int64, error)

func (*Store) CreateAPIToken

func (s *Store) CreateAPIToken(ctx context.Context, t *model.APIToken) (*model.APIToken, error)

func (*Store) CreateAppPlugin

func (s *Store) CreateAppPlugin(ctx context.Context, p *model.AppPlugin) (*model.AppPlugin, error)

func (*Store) CreateAppPluginJob

func (s *Store) CreateAppPluginJob(ctx context.Context, j *model.AppPluginJob) error

func (*Store) CreateAppPluginSigningKey

func (s *Store) CreateAppPluginSigningKey(ctx context.Context, k *model.AppPluginSigningKey) error

func (*Store) CreateChunkedUpload

func (s *Store) CreateChunkedUpload(ctx context.Context, u *model.ChunkedUpload) error

func (*Store) CreateFileGrant

func (s *Store) CreateFileGrant(ctx context.Context, g *model.FileGrant) (*model.FileGrant, error)

CreateFileGrant upserts a grant on the (storage_id, path_prefix, user_id) unique key. Uses a portable check-then-write (UPDATE, else INSERT) so the same code path works for the MySQL driver that wraps this Store — MySQL does not understand SQLite's `ON CONFLICT ... excluded.` upsert.

func (*Store) CreateNFSExport

func (s *Store) CreateNFSExport(ctx context.Context, e *model.NFSExport) (*model.NFSExport, error)

func (*Store) CreateNode

func (s *Store) CreateNode(ctx context.Context, n *model.Node) (*model.Node, error)

func (*Store) CreateNodeComment

func (s *Store) CreateNodeComment(ctx context.Context, c *model.NodeComment) (*model.NodeComment, error)

CreateNodeComment inserts a comment row and returns the stored row (with id + timestamps filled in). Body validation (length, emptiness) belongs to internal/comments — the store persists what it is given.

func (*Store) CreateNodeVersion

func (s *Store) CreateNodeVersion(ctx context.Context, v *model.NodeVersion) (*model.NodeVersion, error)

func (*Store) CreatePlugin

func (s *Store) CreatePlugin(ctx context.Context, p *model.Plugin) (*model.Plugin, error)

func (*Store) CreateProvider

func (s *Store) CreateProvider(ctx context.Context, p *model.Provider) (*model.Provider, error)

func (*Store) CreateReplicaRule

func (s *Store) CreateReplicaRule(ctx context.Context, in *model.ReplicaRuleInput) (*model.ReplicaRule, error)

CreateReplicaRule inserts a new rule.

func (*Store) CreateReplicationTarget

func (s *Store) CreateReplicationTarget(ctx context.Context, rt *model.ReplicationTarget) (*model.ReplicationTarget, error)

func (*Store) CreateS3AccessKey

func (s *Store) CreateS3AccessKey(ctx context.Context, k *model.S3AccessKey) (*model.S3AccessKey, error)

func (*Store) CreateSSHPublicKey

func (s *Store) CreateSSHPublicKey(ctx context.Context, k *model.SSHPublicKey) (*model.SSHPublicKey, error)

func (*Store) CreateSession

func (s *Store) CreateSession(ctx context.Context, userID int64, token string, expiresAt time.Time, ip, ua string) (*model.Session, error)

func (*Store) CreateShare

func (s *Store) CreateShare(ctx context.Context, sh *model.Share) (*model.Share, error)

func (*Store) CreateStagedUpload

func (s *Store) CreateStagedUpload(ctx context.Context, u *model.StagedUpload) error

func (*Store) CreateStorage

func (s *Store) CreateStorage(ctx context.Context, st *model.Storage) (*model.Storage, error)

func (*Store) CreateSyncConflict

func (s *Store) CreateSyncConflict(ctx context.Context, c *model.SyncConflict) error

func (*Store) CreateSyncRun

func (s *Store) CreateSyncRun(ctx context.Context, storageID int64, cursorBefore string) (*model.SyncRun, error)

func (*Store) CreateTag

func (s *Store) CreateTag(ctx context.Context, t *model.Tag) (*model.Tag, error)

CreateTag implements db.Store.

func (*Store) CreateUser

func (s *Store) CreateUser(ctx context.Context, email, passwordHash, role, locale, tz string) (*model.User, error)

func (*Store) CreateWebhookTarget

func (s *Store) CreateWebhookTarget(ctx context.Context, t *model.WebhookTarget) (*model.WebhookTarget, error)

CreateWebhookTarget inserts a new delivery destination and returns the stored row (with id + created_at filled in).

func (*Store) DeleteAPIToken

func (s *Store) DeleteAPIToken(ctx context.Context, id int64) error

func (*Store) DeleteAppPlugin

func (s *Store) DeleteAppPlugin(ctx context.Context, id int64) error

func (*Store) DeleteAppPluginLock

func (s *Store) DeleteAppPluginLock(ctx context.Context, storageID int64, pathHash string) error

func (*Store) DeleteAppPluginState

func (s *Store) DeleteAppPluginState(ctx context.Context, pluginID, storageID int64, pathHash, key string) error

func (*Store) DeleteChunkedUpload

func (s *Store) DeleteChunkedUpload(ctx context.Context, id string) error

func (*Store) DeleteCustomTheme

func (s *Store) DeleteCustomTheme(ctx context.Context, key string) (bool, error)

DeleteCustomTheme removes a theme, reporting whether a row was there.

func (*Store) DeleteExpiredAppPluginLocks

func (s *Store) DeleteExpiredAppPluginLocks(ctx context.Context, now time.Time) (int64, error)

func (*Store) DeleteExpiredChunkedUploads

func (s *Store) DeleteExpiredChunkedUploads(ctx context.Context) error

func (*Store) DeleteExpiredSessions

func (s *Store) DeleteExpiredSessions(ctx context.Context) error

func (*Store) DeleteExpiredShares

func (s *Store) DeleteExpiredShares(ctx context.Context) error

func (*Store) DeleteFileGrant

func (s *Store) DeleteFileGrant(ctx context.Context, id int64) error

func (*Store) DeleteNFSExport

func (s *Store) DeleteNFSExport(ctx context.Context, id, userID int64) error

DeleteNFSExport takes the owner id too — see DeleteS3AccessKey.

func (*Store) DeleteNodeCommentsByNode

func (s *Store) DeleteNodeCommentsByNode(ctx context.Context, nodeID int64) error

DeleteNodeCommentsByNode hard-deletes every comment row of a node — the trash purge hook (belt and suspenders next to the nodes FK CASCADE, which engines without FK enforcement may skip).

func (*Store) DeleteNodeVersion

func (s *Store) DeleteNodeVersion(ctx context.Context, id int64) error

DeleteNodeVersion removes a single version row.

func (*Store) DeleteOldNodeVersions

func (s *Store) DeleteOldNodeVersions(ctx context.Context, nodeID int64, keep int) ([]*model.NodeVersion, error)

DeleteOldNodeVersions deletes all but the newest `keep` versions for a node. Returns the rows that were removed (so the caller can clean storage objects).

func (*Store) DeletePlugin

func (s *Store) DeletePlugin(ctx context.Context, id int64) error

func (*Store) DeleteProvider

func (s *Store) DeleteProvider(ctx context.Context, id int64) error

func (*Store) DeleteReplicaRule

func (s *Store) DeleteReplicaRule(ctx context.Context, id int64) error

DeleteReplicaRule removes a rule.

func (*Store) DeleteReplicationTarget

func (s *Store) DeleteReplicationTarget(ctx context.Context, id int64) error

func (*Store) DeleteS3AccessKey

func (s *Store) DeleteS3AccessKey(ctx context.Context, id, userID int64) error

DeleteS3AccessKey takes the owner id too: deletion is reachable from a self-service surface, and a query scoped to the owner cannot delete another account key even if the handler above it forgets to check.

func (*Store) DeleteSSHPublicKey

func (s *Store) DeleteSSHPublicKey(ctx context.Context, id, userID int64) error

DeleteSSHPublicKey takes the owner id for the same reason DeleteS3AccessKey does: the surface is self-service, and a query scoped to the owner cannot delete somebody else key even if a handler forgets to check.

func (*Store) DeleteSession

func (s *Store) DeleteSession(ctx context.Context, token string) error

func (*Store) DeleteSessionsForUser

func (s *Store) DeleteSessionsForUser(ctx context.Context, userID int64, exceptToken string) error

DeleteSessionsForUser removes every session for the user except the supplied "current" token (so the caller stays signed in after a password change).

func (*Store) DeleteShare

func (s *Store) DeleteShare(ctx context.Context, id int64) error

func (*Store) DeleteStagedUpload

func (s *Store) DeleteStagedUpload(ctx context.Context, id string) error

func (*Store) DeleteStorage

func (s *Store) DeleteStorage(ctx context.Context, id int64) error

func (*Store) DeleteThumbnail

func (s *Store) DeleteThumbnail(ctx context.Context, nodeID int64) error

func (*Store) DeleteUser

func (s *Store) DeleteUser(ctx context.Context, id int64) error

func (*Store) DeleteUserNodeMeta

func (s *Store) DeleteUserNodeMeta(ctx context.Context, userID, nodeID int64, key string) error

DeleteUserNodeMeta removes a single (user, node, key) row.

func (*Store) DeleteWebhookTarget

func (s *Store) DeleteWebhookTarget(ctx context.Context, id int64) error

DeleteWebhookTarget removes a target row.

func (*Store) DestroyAppPluginSigningKey

func (s *Store) DestroyAppPluginSigningKey(ctx context.Context, id string) error

func (*Store) DueAppPluginScheduleItems

func (s *Store) DueAppPluginScheduleItems(ctx context.Context, now time.Time, limit int) ([]*model.AppPluginScheduleItem, error)

func (*Store) ExistingNodeIDs

func (s *Store) ExistingNodeIDs(ctx context.Context, ids []int64) (map[int64]bool, error)

ExistingNodeIDs answers in batches of 500 placeholders — SQLite's default variable ceiling is 999 and the caller feeds it whatever the thumbnail cache directory happens to hold.

func (*Store) FinishAppPluginScheduleItem

func (s *Store) FinishAppPluginScheduleItem(ctx context.Context, pluginID int64, key, status, jobID, errMsg string, rearmAt *time.Time) error

func (*Store) FinishSyncRun

func (s *Store) FinishSyncRun(ctx context.Context, id int64, cursorAfter string, seen, added, updated, deleted int, status, errMsg string) error

func (*Store) GetAPITokenByHash

func (s *Store) GetAPITokenByHash(ctx context.Context, tokenHash string) (*model.APIToken, error)

func (*Store) GetAPITokenByID

func (s *Store) GetAPITokenByID(ctx context.Context, id int64) (*model.APIToken, error)

GetAPITokenByID fetches a token by primary key. Used where a row already references a token and the credential itself was never presented — an S3 access key checking that the token it inherits from is still valid.

func (*Store) GetAppPlugin

func (s *Store) GetAppPlugin(ctx context.Context, id int64) (*model.AppPlugin, error)

func (*Store) GetAppPluginByName

func (s *Store) GetAppPluginByName(ctx context.Context, name string) (*model.AppPlugin, error)

func (*Store) GetAppPluginJob

func (s *Store) GetAppPluginJob(ctx context.Context, id string) (*model.AppPluginJob, error)

func (*Store) GetAppPluginLock

func (s *Store) GetAppPluginLock(ctx context.Context, storageID int64, pathHash string) (*model.AppPluginLock, error)

func (*Store) GetAppPluginSealKey

func (s *Store) GetAppPluginSealKey(ctx context.Context, tenantID, pluginID int64) (*model.AppPluginSigningKey, error)

func (*Store) GetAppPluginSettings

func (s *Store) GetAppPluginSettings(ctx context.Context, pluginID int64) (map[string]string, error)

func (*Store) GetAppPluginSigningCA

func (s *Store) GetAppPluginSigningCA(ctx context.Context, tenantID int64) (*model.AppPluginSigningKey, error)

func (*Store) GetAppPluginSigningKey

func (s *Store) GetAppPluginSigningKey(ctx context.Context, id string) (*model.AppPluginSigningKey, error)

func (*Store) GetAppPluginState

func (s *Store) GetAppPluginState(ctx context.Context, pluginID, storageID int64, pathHash, key string) (string, bool, error)

func (*Store) GetChunkedUpload

func (s *Store) GetChunkedUpload(ctx context.Context, id string) (*model.ChunkedUpload, error)

func (*Store) GetCustomTheme

func (s *Store) GetCustomTheme(ctx context.Context, key string) (*model.CustomTheme, error)

GetCustomTheme returns one theme by slug, or (nil, nil) when there is none.

func (*Store) GetExternalService

func (s *Store) GetExternalService(ctx context.Context, name string) (*db.ExternalService, error)

func (*Store) GetFileGrant

func (s *Store) GetFileGrant(ctx context.Context, id int64) (*model.FileGrant, error)

func (*Store) GetLastSyncRun

func (s *Store) GetLastSyncRun(ctx context.Context, storageID int64) (*model.SyncRun, error)

func (*Store) GetLastSyncRunByStatus

func (s *Store) GetLastSyncRunByStatus(ctx context.Context, storageID int64, status string) (*model.SyncRun, error)

func (*Store) GetNFSExport

func (s *Store) GetNFSExport(ctx context.Context, tokenHash string) (*model.NFSExport, error)

GetNFSExport is the mount path: one indexed read on the hashed secret.

func (*Store) GetNFSExportByID

func (s *Store) GetNFSExportByID(ctx context.Context, id int64) (*model.NFSExport, error)

func (*Store) GetNode

func (s *Store) GetNode(ctx context.Context, id int64) (*model.Node, error)

func (*Store) GetNodeByPath

func (s *Store) GetNodeByPath(ctx context.Context, storageID int64, hash string) (*model.Node, error)

func (*Store) GetNodeByPathIncludingDeleted

func (s *Store) GetNodeByPathIncludingDeleted(ctx context.Context, storageID int64, hash string) (*model.Node, error)

GetNodeByPathIncludingDeleted returns the row at a path, live or trashed.

⚠ ORDER BY is load-bearing since migration 00032 made the unique index over (storage_id, path_hash) live-only: several trashed rows may now share a path with at most one live one. `deleted_at IS NULL` sorts the live row first (0 before 1), and id DESC picks the most recent among the trashed. Without it the sync worker's view of a path would depend on row order.

func (*Store) GetNodeComment

func (s *Store) GetNodeComment(ctx context.Context, id int64) (*model.NodeComment, error)

GetNodeComment returns a single live (not soft-deleted) comment by id.

func (*Store) GetNodeOwner

func (s *Store) GetNodeOwner(ctx context.Context, nodeID int64) (*int64, error)

GetNodeOwner returns the owner_id (nullable) for one node.

func (*Store) GetNodeVersion

func (s *Store) GetNodeVersion(ctx context.Context, id int64) (*model.NodeVersion, error)

GetNodeVersion looks up a single version row by id.

func (*Store) GetNotification

func (s *Store) GetNotification(ctx context.Context, id int64) (*model.Notification, error)

GetNotification returns a single row by id.

func (*Store) GetNotificationSettings

func (s *Store) GetNotificationSettings(ctx context.Context, userID int64) (*model.NotificationSettings, error)

GetNotificationSettings returns the per-user toggle. A missing row is treated as the default (in_app_enabled=true, no muted events).

func (*Store) GetPlugin

func (s *Store) GetPlugin(ctx context.Context, id int64) (*model.Plugin, error)

func (*Store) GetPluginByName

func (s *Store) GetPluginByName(ctx context.Context, name string) (*model.Plugin, error)

func (*Store) GetProvider

func (s *Store) GetProvider(ctx context.Context, id int64) (*model.Provider, error)

func (*Store) GetProviderByHost

func (s *Store) GetProviderByHost(ctx context.Context, host string) (*model.Provider, error)

func (*Store) GetProviderBySlug

func (s *Store) GetProviderBySlug(ctx context.Context, slug string) (*model.Provider, error)

func (*Store) GetProviderIDForStorage

func (s *Store) GetProviderIDForStorage(ctx context.Context, storageID int64) (int64, bool, error)

func (*Store) GetProviderPlan

func (s *Store) GetProviderPlan(ctx context.Context, providerID int64) (string, string, string, error)

func (*Store) GetReplicaRule

func (s *Store) GetReplicaRule(ctx context.Context, id int64) (*model.ReplicaRule, error)

GetReplicaRule returns a single rule by id.

func (*Store) GetReplicaSettings

func (s *Store) GetReplicaSettings(ctx context.Context) (*model.ReplicaSettings, error)

GetReplicaSettings returns the singleton row. Missing row maps to defaults (mirror, no cron).

func (*Store) GetReplicaStatusReport

func (s *Store) GetReplicaStatusReport(ctx context.Context) (*model.ReplicaStatusReport, error)

GetReplicaStatusReport returns the singleton row. nil + nil err when no report has been generated yet.

func (*Store) GetReplicationTarget

func (s *Store) GetReplicationTarget(ctx context.Context, id int64) (*model.ReplicationTarget, error)

func (*Store) GetS3AccessKey

func (s *Store) GetS3AccessKey(ctx context.Context, accessKeyID string) (*model.S3AccessKey, error)

GetS3AccessKey is the hot path: every signed request looks its key up here, so it is a single indexed read and nothing more.

func (*Store) GetS3AccessKeyByID

func (s *Store) GetS3AccessKeyByID(ctx context.Context, id int64) (*model.S3AccessKey, error)

func (*Store) GetSSHPublicKey

func (s *Store) GetSSHPublicKey(ctx context.Context, fingerprint string) (*model.SSHPublicKey, error)

GetSSHPublicKey is the login path: one indexed read on the fingerprint.

func (*Store) GetSSHPublicKeyByID

func (s *Store) GetSSHPublicKeyByID(ctx context.Context, id int64) (*model.SSHPublicKey, error)

func (*Store) GetSessionByToken

func (s *Store) GetSessionByToken(ctx context.Context, token string) (*model.Session, error)

func (*Store) GetSessionIDToken

func (s *Store) GetSessionIDToken(ctx context.Context, token string) (string, error)

GetSessionIDToken implements db.Store: "" for a session without one or no session at all. Expiry is deliberately not checked — the IdP accepts an expired id_token as a hint, and sign-out is exactly when it has expired.

func (*Store) GetSetting

func (s *Store) GetSetting(ctx context.Context, key string) (string, error)

func (*Store) GetShareByID

func (s *Store) GetShareByID(ctx context.Context, id int64) (*model.Share, error)

func (*Store) GetShareByToken

func (s *Store) GetShareByToken(ctx context.Context, token string) (*model.Share, error)

func (*Store) GetStagedUpload

func (s *Store) GetStagedUpload(ctx context.Context, id string) (*model.StagedUpload, error)

func (*Store) GetStagedUploadByNode

func (s *Store) GetStagedUploadByNode(ctx context.Context, nodeID int64) (*model.StagedUpload, error)

func (*Store) GetStorage

func (s *Store) GetStorage(ctx context.Context, id int64) (*model.Storage, error)

func (*Store) GetStorageByName

func (s *Store) GetStorageByName(ctx context.Context, name string) (*model.Storage, error)

func (*Store) GetStorageByUID

func (s *Store) GetStorageByUID(ctx context.Context, uid string) (*model.Storage, error)

GetStorageByUID resolves the address that does not move. ⚠ An empty uid must never match: on an install migrated from before the column existed a row could carry one, and "" would then resolve to whichever came first.

func (*Store) GetSupertenant

func (s *Store) GetSupertenant(ctx context.Context) (*model.Provider, error)

func (*Store) GetSyncRun

func (s *Store) GetSyncRun(ctx context.Context, id int64) (*model.SyncRun, error)

func (*Store) GetThumbnail

func (s *Store) GetThumbnail(ctx context.Context, nodeID int64) (*model.Thumbnail, error)

func (*Store) GetUser

func (s *Store) GetUser(ctx context.Context, id int64) (*model.User, error)

func (*Store) GetUserByEmail

func (s *Store) GetUserByEmail(ctx context.Context, email string) (*model.User, error)

func (*Store) GetUserByProviderEmail

func (s *Store) GetUserByProviderEmail(ctx context.Context, providerID int64, email string) (*model.User, error)

GetUserByProviderEmail looks a user up within a single provider (tenant), the multi-tenant analogue of GetUserByEmail. Returns (nil, nil) if absent.

func (*Store) GetUserByUsername

func (s *Store) GetUserByUsername(ctx context.Context, username string) (*model.User, error)

GetUserByUsername is the username half of dual-side login (migration 00025). Callers should reach it through identity.Resolve rather than directly, so the e-mail/username disambiguation lives in one place.

func (*Store) GetUserDisplayNames

func (s *Store) GetUserDisplayNames(ctx context.Context, ids []int64) (map[int64]string, error)

GetUserDisplayNames answers "what do I call these ids" for a whole listing page in ONE query.

⚠ It deliberately returns names, not users. The Owner column needs a label and nothing else, and hydrating full user rows to read one field would drag password hashes, TOTP secrets and recovery codes through the listing path for every account that happens to own a file in the folder.

The fallback chain is display_name → username → email, because a row with an empty display_name is common (OIDC providers that send no name) and an Owner column that reads blank is worse than one that reads an address. The chain is model.PersonLabel — the one rule every screen names a person by — applied in Go, not re-typed as a COALESCE in each dialect's SQL.

func (*Store) GetUserNodeMeta

func (s *Store) GetUserNodeMeta(ctx context.Context, userID, nodeID int64, key string) (string, error)

GetUserNodeMeta fetches a single value (returns empty string + sql.ErrNoRows if absent).

func (*Store) GetUserPrefs

func (s *Store) GetUserPrefs(ctx context.Context, userID int64, surface string) (string, error)

GetUserPrefs returns the raw JSON document for one person on one surface, or "" when they have never stored one.

⚠ "" and "no row" are the same answer and neither is an error: "this person has not chosen anything yet" is the ordinary case for every account on its first day, on every surface they have not opened.

func (*Store) GetUserUsage

func (s *Store) GetUserUsage(ctx context.Context, userID int64) (int64, int64, error)

GetUserUsage returns (used_bytes, quota_bytes).

func (*Store) GetUserViewPrefs

func (s *Store) GetUserViewPrefs(ctx context.Context, userID int64) (string, error)

GetUserViewPrefs returns the raw JSON document for a user, or "" when the user has never stored one.

⚠ "" and "no row" are the same answer on purpose, and neither is an error: "this person has not arranged any folders yet" is the ordinary case for every account on its first day, and a caller forced to distinguish sql.ErrNoRows from an empty column would get it wrong once and log a scary line every time somebody signed in.

func (*Store) GetWebhookTarget

func (s *Store) GetWebhookTarget(ctx context.Context, id int64) (*model.WebhookTarget, error)

GetWebhookTarget returns a single target by id.

func (*Store) HardDeleteNode

func (s *Store) HardDeleteNode(ctx context.Context, id int64) error

func (*Store) IncrementShareDownload

func (s *Store) IncrementShareDownload(ctx context.Context, id int64) error

func (*Store) IncrementShareUpload

func (s *Store) IncrementShareUpload(ctx context.Context, id int64, n int) error

func (*Store) IncrementShareVisit

func (s *Store) IncrementShareVisit(ctx context.Context, id int64) error

IncrementShareVisit counts one opening of an app page (00052): what the page's `max_visits` ceiling is measured against, and never a download.

func (*Store) IncrementUserUsage

func (s *Store) IncrementUserUsage(ctx context.Context, userID int64, delta int64) error

IncrementUserUsage atomically adjusts usage_bytes (delta may be negative); clamps the resulting value at 0 to keep it sane.

⚠ Not `MAX(0, …)`. SQLite has a two-argument scalar max(); in MySQL, which this Store also serves, MAX is an aggregate only and the statement was a syntax error. quotastore logs that error and lets the write through, so on MySQL every upload succeeded, usage_bytes never moved, and no quota was ever enforced. CASE means the same thing to both engines.

func (*Store) InsertAuditEntry

func (s *Store) InsertAuditEntry(ctx context.Context, e *model.AuditEntry) error

func (*Store) InsertNotification

func (s *Store) InsertNotification(ctx context.Context, n *model.NotificationInput) (int64, error)

InsertNotification persists a new in-app notification row. Webhook status starts at "pending" — Service.Send updates it after the HTTP attempt finishes. meta_json is normalized to "{}" when empty so the scan path always finds valid JSON.

func (*Store) LinkNodeTags

func (s *Store) LinkNodeTags(ctx context.Context, nodeID int64, add, remove []int64) error

LinkNodeTags implements db.Store.

The link insert is an upsert that changes nothing, so adding a tag a file already carries is not an error on either engine (MySQL has no ON CONFLICT DO NOTHING; the rewrite in upsert turns this into ON DUPLICATE KEY UPDATE).

func (*Store) LinkProviderStorage

func (s *Store) LinkProviderStorage(ctx context.Context, providerID, storageID int64) error

func (*Store) ListAPITokens

func (s *Store) ListAPITokens(ctx context.Context) ([]*model.APIToken, error)

func (*Store) ListAPITokensByUser

func (s *Store) ListAPITokensByUser(ctx context.Context, userID int64) ([]*model.APIToken, error)

func (*Store) ListAllFileGrants

func (s *Store) ListAllFileGrants(ctx context.Context) ([]*model.FileGrant, error)

func (*Store) ListAllShares

func (s *Store) ListAllShares(ctx context.Context, creatorID *int64, activeOnly bool, limit, offset int) ([]*db.ShareWithMeta, int64, error)

ListAllShares returns the admin overview of every share. `creatorID` nil means all users; activeOnly excludes expired/revoked rows.

func (*Store) ListAppPluginJobsByOp

func (s *Store) ListAppPluginJobsByOp(ctx context.Context, opIDs []int64) (map[int64]*model.AppPluginJob, error)

func (*Store) ListAppPluginLocks

func (s *Store) ListAppPluginLocks(ctx context.Context, storageID int64) ([]*model.AppPluginLock, error)

func (*Store) ListAppPluginOverrides

func (s *Store) ListAppPluginOverrides(ctx context.Context, pluginID int64) ([]*model.AppPluginOverride, error)

func (*Store) ListAppPluginScheduleItems

func (s *Store) ListAppPluginScheduleItems(ctx context.Context, pluginID int64) ([]*model.AppPluginScheduleItem, error)

func (*Store) ListAppPluginShares

func (s *Store) ListAppPluginShares(ctx context.Context, pluginID int64, activeOnly bool, limit, offset int) ([]*db.ShareWithMeta, int64, error)

ListAppPluginShares is the admin view of the links APPS opened — the signature requests an e-signature plugin sent out, and every other public page an installed app is holding. pluginID 0 means every app; it never means every share, which is what ListAllShares is for.

func (*Store) ListAppPluginSigningCAs

func (s *Store) ListAppPluginSigningCAs(ctx context.Context, tenantID int64) ([]*model.AppPluginSigningKey, error)

func (*Store) ListAppPluginStateFiles

func (s *Store) ListAppPluginStateFiles(ctx context.Context, pluginID int64, key string, limit int) ([]*model.AppPluginStateFile, error)

func (*Store) ListAppPluginStateKeys

func (s *Store) ListAppPluginStateKeys(ctx context.Context, storageID int64, pathHashes []string) (map[string][]string, error)

func (*Store) ListAppPlugins

func (s *Store) ListAppPlugins(ctx context.Context) ([]*model.AppPlugin, error)

func (*Store) ListAuditFiltered

func (s *Store) ListAuditFiltered(ctx context.Context, userID *int64, action string, from, to *time.Time, limit, offset int) ([]*db.AuditEntryWithUser, int64, error)

ListAuditFiltered returns paginated audit entries with user_email join + filters.

func (*Store) ListAuditRecent

func (s *Store) ListAuditRecent(ctx context.Context, limit int) ([]*model.AuditEntry, error)

func (*Store) ListConflictsByStorage

func (s *Store) ListConflictsByStorage(ctx context.Context, storageID int64, limit int) ([]*model.SyncConflict, error)

ListConflictsByStorage returns the most recent unresolved conflicts for one storage — used by /api/admin/storages/:id/drift.

func (*Store) ListCustomThemes

func (s *Store) ListCustomThemes(ctx context.Context) ([]*model.CustomTheme, error)

ListCustomThemes returns every stored theme, oldest first.

⚠ Ordered by id and not by name: this is the order the palette cards appear in, and re-sorting the moment somebody renames a theme moves the card a person was about to click.

func (*Store) ListDuplicateNodes

func (s *Store) ListDuplicateNodes(ctx context.Context, minSize int64) ([]db.DuplicateNode, error)

ListDuplicateNodes returns every live file node whose (size, non-empty etag) pair occurs more than once — the raw rows behind the admin duplicate report. Plain GROUP BY … HAVING in a derived table, so the same SQL runs on SQLite and MySQL (this driver backs both).

func (*Store) ListEnabledStorages

func (s *Store) ListEnabledStorages(ctx context.Context) ([]*model.Storage, error)

func (*Store) ListExternalServices

func (s *Store) ListExternalServices(ctx context.Context) ([]*db.ExternalService, error)

func (*Store) ListFileGrantsByStorage

func (s *Store) ListFileGrantsByStorage(ctx context.Context, storageID int64) ([]*model.FileGrant, error)

func (*Store) ListFileGrantsByStorageUser

func (s *Store) ListFileGrantsByStorageUser(ctx context.Context, storageID, userID int64) ([]*model.FileGrant, error)

func (*Store) ListIdleStagedUploads

func (s *Store) ListIdleStagedUploads(ctx context.Context, before time.Time, limit int) ([]*model.StagedUpload, error)

func (*Store) ListLiveNodesInTrash

func (s *Store) ListLiveNodesInTrash(ctx context.Context, storageID int64, trashPrefix string) ([]*model.Node, error)

ListLiveNodesInTrash returns live rows sitting in the trash bucket. See the db.Store declaration for why any such row is a defect to be cleaned up.

func (*Store) ListNFSExports

func (s *Store) ListNFSExports(ctx context.Context, userID int64) ([]*model.NFSExport, error)

func (*Store) ListNodeComments

func (s *Store) ListNodeComments(ctx context.Context, nodeID int64) ([]*model.NodeComment, error)

ListNodeComments returns the live comments of one node in chronological order (oldest first), each carrying the author's display name (falling back to the author's email).

func (*Store) ListNodeIDsWithVersions

func (s *Store) ListNodeIDsWithVersions(ctx context.Context) ([]int64, error)

ListNodeIDsWithVersions returns the distinct node ids holding at least one version row — the work list for the daily retention job.

func (*Store) ListNodeTags

func (s *Store) ListNodeTags(ctx context.Context, nodeID int64) ([]*model.Tag, error)

ListNodeTags implements db.Store.

func (*Store) ListNodeVersions

func (s *Store) ListNodeVersions(ctx context.Context, nodeID int64) ([]*model.NodeVersion, error)

func (*Store) ListNodesByParent

func (s *Store) ListNodesByParent(ctx context.Context, storageID int64, parentID *int64) ([]*model.Node, error)

func (*Store) ListNodesByTagIDs

func (s *Store) ListNodesByTagIDs(ctx context.Context, tagIDs []int64, limit int) ([]*model.Node, error)

ListNodesByTagIDs implements db.Store.

func (*Store) ListNodesByUserMeta

func (s *Store) ListNodesByUserMeta(ctx context.Context, userID int64, key string, limit int) ([]*model.Node, error)

ListNodesByUserMeta returns the nodes flagged with (key) for the given user, joined with the live node row, ordered by user_node_meta.updated_at DESC.

func (*Store) ListNodesUnder

func (s *Store) ListNodesUnder(ctx context.Context, storageID int64, dir string, includeDeleted bool) ([]*model.Node, error)

func (*Store) ListNotifications

func (s *Store) ListNotifications(ctx context.Context, userID *int64, onlyUnread bool, mutedEvents, hiddenBodies []string, broadcasts model.BroadcastFilter, limit, offset int) ([]*model.Notification, int64, error)

ListNotifications paginates either a user's view (broadcasts + user-scoped) or admin/global view (userID == nil).

onlyUnread keeps the rows still unread for the reader. mutedEvents drops the event ids the user has muted; empty means no mute filter. hiddenBodies drops rows whose body matches one of the LIKE patterns (see db.Store). broadcasts decides which broadcasts the bell takes at all and whose read state they carry (see db.Store).

func (*Store) ListPlugins

func (s *Store) ListPlugins(ctx context.Context) ([]*model.Plugin, error)

func (*Store) ListProviderStorageIDs

func (s *Store) ListProviderStorageIDs(ctx context.Context, providerID int64) ([]int64, error)

func (*Store) ListProviders

func (s *Store) ListProviders(ctx context.Context) ([]*model.Provider, error)

func (*Store) ListReplicaFailures

func (s *Store) ListReplicaFailures(ctx context.Context, onlyUnresolved bool, limit, offset int) ([]*model.ReplicaFailure, int64, error)

ListReplicaFailures paginates either all rows or only unresolved.

func (*Store) ListReplicaRules

func (s *Store) ListReplicaRules(ctx context.Context) ([]*model.ReplicaRule, error)

ListReplicaRules returns the rule list ordered priority asc.

func (*Store) ListReplicationTargets

func (s *Store) ListReplicationTargets(ctx context.Context) ([]*model.ReplicationTarget, error)

func (*Store) ListS3AccessKeys

func (s *Store) ListS3AccessKeys(ctx context.Context, userID int64) ([]*model.S3AccessKey, error)

func (*Store) ListSSHPublicKeys

func (s *Store) ListSSHPublicKeys(ctx context.Context, userID int64) ([]*model.SSHPublicKey, error)

func (*Store) ListSettings

func (s *Store) ListSettings(ctx context.Context) (map[string]string, error)

func (*Store) ListSharesByNode

func (s *Store) ListSharesByNode(ctx context.Context, nodeID int64) ([]*model.Share, error)

func (*Store) ListStagedUploads

func (s *Store) ListStagedUploads(ctx context.Context, state string, limit int) ([]*model.StagedUpload, error)

func (*Store) ListStaleNodes

func (s *Store) ListStaleNodes(ctx context.Context, storageID int64, before time.Time) ([]*model.Node, error)

func (*Store) ListStaleNodesUnder

func (s *Store) ListStaleNodesUnder(ctx context.Context, storageID int64, dir string, before time.Time) ([]*model.Node, error)

func (*Store) ListStorages

func (s *Store) ListStorages(ctx context.Context) ([]*model.Storage, error)

func (*Store) ListSyncConflictsByRun

func (s *Store) ListSyncConflictsByRun(ctx context.Context, runID int64) ([]*model.SyncConflict, error)

ListSyncConflictsByRun returns conflicts attributed to a specific sync_run.

V0.1 schema does not link conflicts to a run; we approximate by returning conflicts detected within the run's time window (best effort).

func (*Store) ListSyncConflictsByStorage

func (s *Store) ListSyncConflictsByStorage(ctx context.Context, storageID int64, limit int) ([]*model.SyncConflict, error)

ListSyncConflictsByStorage returns recent unresolved conflicts.

func (*Store) ListSyncRuns

func (s *Store) ListSyncRuns(ctx context.Context, storageID int64, limit int) ([]*model.SyncRun, error)

func (*Store) ListSyncRunsAcrossAll

func (s *Store) ListSyncRunsAcrossAll(ctx context.Context, storageID int64, status string, limit, offset int) ([]*model.SyncRun, int64, error)

ListSyncRunsAcrossAll returns paginated runs across every storage, optionally filtered by storageID (0=all) and status (""=all).

Runs older than 5 days are filtered out — the admin Sync history page only cares about recent activity, and older runs clutter the list (a busy storage produces hundreds per day).

func (*Store) ListTagPlacements

func (s *Store) ListTagPlacements(ctx context.Context, q model.TagQuery) ([]model.TagPlacement, error)

ListTagPlacements implements db.Store.

func (*Store) ListTags

func (s *Store) ListTags(ctx context.Context, q model.TagQuery) ([]*model.Tag, error)

ListTags implements db.Store.

func (*Store) ListTrashed

func (s *Store) ListTrashed(ctx context.Context, storageID *int64, limit, offset int) ([]*model.Node, int, error)

ListTrashed returns paginated soft-deleted rows, optionally narrowed to a single storage. Total count returned alongside so the UI can paginate.

func (*Store) ListTrashedExpired

func (s *Store) ListTrashedExpired(ctx context.Context, before time.Time, storageIDs []int64, afterID int64, limit int) ([]*model.Node, error)

ListTrashedExpired returns soft-deleted nodes whose deleted_at is older than `before`, in id order after `afterID`, narrowed to storageIDs (see db.Store for why the id, and why the narrowing is in the SQL).

func (*Store) ListUnresolvedConflicts

func (s *Store) ListUnresolvedConflicts(ctx context.Context) ([]*model.SyncConflict, error)

func (*Store) ListUnstoredNodes

func (s *Store) ListUnstoredNodes(ctx context.Context, afterID int64, limit int) ([]*model.Node, error)

func (*Store) ListUserNodeMetaForNode

func (s *Store) ListUserNodeMetaForNode(ctx context.Context, userID, nodeID int64, prefix string) (map[string]string, error)

ListUserNodeMetaForNode returns all (key,value) for one (user,node) pair, optionally restricted to keys that start with `prefix`.

func (*Store) ListUsers

func (s *Store) ListUsers(ctx context.Context) ([]*model.User, error)

func (*Store) ListUsersByProvider

func (s *Store) ListUsersByProvider(ctx context.Context, providerID int64) ([]*model.User, error)

ListUsersByProvider lists a tenant's users (provider admin + delete-cascade).

func (*Store) ListWebhookTargets

func (s *Store) ListWebhookTargets(ctx context.Context) ([]*model.WebhookTarget, error)

ListWebhookTargets returns every target ordered by id. Enabled/event filtering happens in the notify dispatcher, not in SQL — the table is tiny and the admin list needs disabled rows too.

func (*Store) LookupParentByPath

func (s *Store) LookupParentByPath(ctx context.Context, storageID int64, fullPath string) (*int64, error)

LookupParentByPath returns parent_id (nil at root) for `fullPath`'s parent dir, by walking the cache one segment at a time.

func (*Store) MarkAllBroadcastsRead

func (s *Store) MarkAllBroadcastsRead(ctx context.Context, readerID int64) error

MarkAllBroadcastsRead moves readerID's "mark all read" point to the newest notification and drops the single marks it has overtaken.

⚠ The point only moves forward: `read_at` is assigned FIRST and compares against the old `through_id`. MySQL applies ON DUPLICATE KEY assignments left to right, so in the other order it would already see the new value; SQLite evaluates every assignment against the old row, so either order is right there.

func (*Store) MarkAllNotificationsRead

func (s *Store) MarkAllNotificationsRead(ctx context.Context, userID *int64) error

MarkAllNotificationsRead bumps read_at for every unread row addressed to userID — never a broadcast, see MarkNotificationRead. Pass nil for the global "mark all" admin sweep.

func (*Store) MarkBroadcastsRead

func (s *Store) MarkBroadcastsRead(ctx context.Context, readerID int64, ids []int64) error

MarkBroadcastsRead records readerID's marks on the given broadcasts. Ids that are not unread broadcasts are dropped first — a row addressed to a user keeps its read state on the row, and a broadcast stamped through the shared column before 00056 is already read for everyone.

⚠ Two statements, not INSERT … SELECT: MySQL resolves the no-op upsert's column against the SELECT's tables too, and notifications has columns of the same names. The select's rows are closed before the insert — SQLite runs on one connection.

func (*Store) MarkNotificationRead

func (s *Store) MarkNotificationRead(ctx context.Context, id int64, userID *int64) error

MarkNotificationRead bumps read_at on a single row. With a userID the row must be ADDRESSED to that user: a broadcast is many readers' row and is marked per reader by MarkBroadcastsRead.

func (*Store) MoveNode

func (s *Store) MoveNode(ctx context.Context, id int64, parentID *int64, name, path, hash string) error

MoveNode re-homes a node: new parent, name, path and path hash — and, for a LIVE row, the storage_key that must mirror that path.

⚠ storage_key is not decoration. It is what internal/versioning, the antivirus quarantine, the id-addressed download (`Manager.Read`) and the sync tombstone pass hand to the driver as the file's key, each of them preferring it over `path`. Leaving it at the pre-move value made every one of those address a path the file no longer occupies, and every one of them fails SILENTLY on a miss: the snapshot before an overwrite records nothing and lets the write through, the quarantine reports success while the infected bytes stay live, `confirmGone` tombstones a file that is fine, and a download by id 404s on a file the listing shows.

⚠⚠ The CASE is the trash exception and it is load-bearing. On a trashed row storage_key deliberately holds the ORIGINAL path (SoftDeleteAndRetag writes it) — that is the only record of where trash.Service.Restore has to put the file back, and sync.reconcileTrash reads it to tell a restorable deletion from a row that has to be hard-deleted. Overwriting it here would destroy both. Live rows mirror path; trashed rows keep their origin.

func (*Store) NextAppPluginScheduleDue

func (s *Store) NextAppPluginScheduleDue(ctx context.Context) (*time.Time, error)

NextAppPluginScheduleDue answers with ORDER BY … LIMIT 1 rather than MIN(due_at): MIN over no rows is one NULL row, which scans into a time.Time as a type error instead of ErrNoRows, and "nothing is due" is the ordinary state of a quiet instance, not a failure to report.

func (*Store) NextNodeVersionNumber

func (s *Store) NextNodeVersionNumber(ctx context.Context, nodeID int64) (int, error)

NextNodeVersionNumber returns COALESCE(MAX(version_n),0)+1 for a node.

func (*Store) Ping

func (s *Store) Ping(ctx context.Context) error

Ping implements db.Store.

func (*Store) PutAppPluginLock

func (s *Store) PutAppPluginLock(ctx context.Context, l *model.AppPluginLock) error

func (*Store) PutAppPluginOverrides

func (s *Store) PutAppPluginOverrides(ctx context.Context, pluginID int64, list []*model.AppPluginOverride) error

func (*Store) PutAppPluginScheduleItem

func (s *Store) PutAppPluginScheduleItem(ctx context.Context, it *model.AppPluginScheduleItem) error

PutAppPluginScheduleItem writes the item, replacing an existing one unless it is RUNNING — a row another process holds the lease on is its business, not ours, and stomping it would let the same work run twice.

Delete-then-insert rather than an upsert: the two engines this file serves spell upserts differently, and the read is needed anyway to see the lease.

func (*Store) PutAppPluginSettings

func (s *Store) PutAppPluginSettings(ctx context.Context, pluginID int64, values map[string]string) error

func (*Store) ReapAppPluginScheduleItems

func (s *Store) ReapAppPluginScheduleItems(ctx context.Context, before time.Time) (int64, error)

func (*Store) RecomputeUserUsage

func (s *Store) RecomputeUserUsage(ctx context.Context, userID int64) (int64, error)

RecomputeUserUsage scans the file nodes owned by this user, sets usage_bytes to the sum of their sizes, and returns the value.

⚠ TRASHED ROWS ARE INCLUDED — there is deliberately no `deleted_at IS NULL` here. Trashed bytes still occupy the storage and still count against the ceiling; the purge is the only release point (docs/QUOTAS.md). The filter used to exclude them, which put this reconciler at odds with the incremental accounting: a recompute forgave every trashed byte, and the SubUsage at purge then subtracted them a second time — clamped at zero, so the drift was silent.

func (*Store) ReleaseShareDownload

func (s *Store) ReleaseShareDownload(ctx context.Context, id int64) error

ReleaseShareDownload hands a reserved slot back, never below zero.

func (*Store) ReserveShareDownload

func (s *Store) ReserveShareDownload(ctx context.Context, id int64) (bool, error)

ReserveShareDownload claims one download against the cap in a single statement, so overlapping requests cannot all pass a check that each of them read before any of them wrote. False = the cap is already spent.

func (*Store) ResolveConflict

func (s *Store) ResolveConflict(ctx context.Context, id int64, resolution string) error

func (*Store) ResolveReplicaFailure

func (s *Store) ResolveReplicaFailure(ctx context.Context, path, op string) error

ResolveReplicaFailure stamps resolved_at on the matching row. Missing rows are a no-op.

func (*Store) RestoreNode

func (s *Store) RestoreNode(ctx context.Context, id int64) error

RestoreNode flips deleted_at back to NULL.

func (*Store) RestoreNodeAt

func (s *Store) RestoreNodeAt(ctx context.Context, id int64, parentID *int64, origPath string) error

RestoreNodeAt flips deleted_at to NULL while reverting path/parent.

Used by trash.Service after `vfDelete` left `storage_key` holding the original path (and `path` holding the trash key). Caller resolves `parentID` via `LookupParentByPath`.

func (*Store) RetireAppPluginSigningCA

func (s *Store) RetireAppPluginSigningCA(ctx context.Context, tenantID int64) error

func (*Store) RevokeShare

func (s *Store) RevokeShare(ctx context.Context, id int64) error

RevokeShare soft-revokes by setting expires_at = NOW. Audit trail is kept (the row is not deleted).

func (*Store) SearchNodes

func (s *Store) SearchNodes(ctx context.Context, storageID int64, m model.NameMatch, limit int) ([]*model.Node, error)

SearchNodes — see db.Store. Every condition is on the name, which idx_nodes_storage_parent_name holds, so SQLite turns a row away without reading it from the table (a condition on the path read every candidate row — 1.06 s for an eleven-word query on the 169k-file catalogue of PR #46). In the order a row meets them:

  1. The engine's own LIKE on the stored bytes — cheap, in C: m.Runs, and every word made only of letters every stored spelling holds as it is (namefold.AllPlain: `plan`, `2026`). For those the native LIKE IS the normaliser's answer, give or take a mark composing onto the word's last letter, which the scorer re-checks.
  2. Every other word through the normaliser: fx_match on SQLite (fold.go), one call a row for all of them. MySQL can compose nothing, so it gets its accent- and case-insensitive collation over both the composed and the decomposed form of each word, on the name with the i's that collation keeps apart made one (mysqlNameLike).
  3. m.Prefer ranks before the LIMIT. A plain word natively; any other only for the rows that natively start with its plain prefix, since a Go function in an ORDER BY runs for EVERY matching row — measured: 1.2 s for `plan` over 170 000 rows that all held it, 0.2 s without.

⚠ The escape character is spelled out on SQLite and must NOT be on MySQL. SQLite has none unless the statement names one; MySQL escapes with `\` by default, and `'\'` is an unterminated string literal in its dialect. ⚠ On MySQL, nodes.name compares byte for byte since migration 00041 — two files that differ only by case are two files — so a search names the collation it wants explicitly.

func (*Store) SetAppPluginJobOp

func (s *Store) SetAppPluginJobOp(ctx context.Context, jobID string, opID int64) error

func (*Store) SetAppPluginState

func (s *Store) SetAppPluginState(ctx context.Context, pluginID, storageID int64, pathHash, rel, key, value string) error

func (*Store) SetNFSExportDisabled

func (s *Store) SetNFSExportDisabled(ctx context.Context, id int64, disabled bool) error

func (*Store) SetNodeActor

func (s *Store) SetNodeActor(ctx context.Context, nodeID int64, actorID *int64) error

SetNodeActor updates the last_actor_id column for one node. A nil actor is SYSTEM — a change that arrived from outside filex has nobody to name, and writing the previous actor there instead would be a lie the UI cannot see through.

func (*Store) SetNodeExternalUpload

func (s *Store) SetNodeExternalUpload(ctx context.Context, nodeID int64, external bool) error

SetNodeExternalUpload marks (or unmarks) a node as having arrived through an anonymous drop link. Only ever set to true, by the drop handler.

func (*Store) SetNodeMtime

func (s *Store) SetNodeMtime(ctx context.Context, id int64, mtime *time.Time) error

func (*Store) SetNodeOwner

func (s *Store) SetNodeOwner(ctx context.Context, nodeID int64, ownerID *int64) error

SetNodeOwner updates the owner_id column for one node.

func (*Store) SetNodeSize

func (s *Store) SetNodeSize(ctx context.Context, id int64, size int64) error

func (*Store) SetNodeTransferState

func (s *Store) SetNodeTransferState(ctx context.Context, nodeID int64, state string) error

func (*Store) SetProviderPlan

func (s *Store) SetProviderPlan(ctx context.Context, providerID int64, plan, limitsJSON, billingRef string) error

func (*Store) SetS3AccessKeyDisabled

func (s *Store) SetS3AccessKeyDisabled(ctx context.Context, id int64, disabled bool) error

func (*Store) SetSSHPublicKeyDisabled

func (s *Store) SetSSHPublicKeyDisabled(ctx context.Context, id int64, disabled bool) error

func (*Store) SetSessionIDToken

func (s *Store) SetSessionIDToken(ctx context.Context, token, idToken string) error

SetSessionIDToken implements db.Store (migration 00057).

func (*Store) SetThumbnailState

func (s *Store) SetThumbnailState(ctx context.Context, nodeID int64, state, errMsg string) error

func (*Store) SetTotpPendingSecret

func (s *Store) SetTotpPendingSecret(ctx context.Context, id int64, secret string, recoveryCodes []string) error

SetTotpPendingSecret stores a freshly-enrolled TOTP secret + recovery codes prior to the user verifying with a one-time code.

func (*Store) SetUserEnabled

func (s *Store) SetUserEnabled(ctx context.Context, userID int64, enabled bool) error

SetUserEnabled flips the account on/off. Files, quota and grants are untouched -- this is an access switch, not a soft delete.

func (*Store) SetUserNodeMeta

func (s *Store) SetUserNodeMeta(ctx context.Context, userID, nodeID int64, key, value string) error

SetUserNodeMeta upserts a (user, node, key) row.

func (*Store) SetUserPrefs

func (s *Store) SetUserPrefs(ctx context.Context, userID int64, surface, doc string) error

SetUserPrefs replaces the whole document for one person on one surface.

func (*Store) SetUserProvider

func (s *Store) SetUserProvider(ctx context.Context, userID, providerID int64, oidcSubject string) error

SetUserProvider re-homes a user to a provider (tenant) and records its OIDC subject. Used by OIDC JIT to stamp the host-resolved tenant. Passing an empty oidcSubject leaves the column as-is is NOT done here — it is overwritten, so callers should pass the current value when only changing the provider.

func (*Store) SetUserQuota

func (s *Store) SetUserQuota(ctx context.Context, userID int64, bytes int64) error

SetUserQuota sets the quota_bytes value for a user (0 = unlimited).

func (*Store) SetUserUsername

func (s *Store) SetUserUsername(ctx context.Context, id int64, username string) error

SetUserUsername claims a login name. The unique index — not any check above this call — is what actually guarantees uniqueness, so a caller racing another creation gets an error here and is expected to try another name.

func (*Store) SetUserViewPrefs

func (s *Store) SetUserViewPrefs(ctx context.Context, userID int64, doc string) error

SetUserViewPrefs replaces the whole document for a user.

func (*Store) SoftDeleteAndRetag

func (s *Store) SoftDeleteAndRetag(ctx context.Context, id int64, trashPath, trashHash, origPath string) error

SoftDeleteAndRetag is the trash-aware soft-delete: it sets deleted_at, rewrites path/path_hash to the supplied trash key, and stashes the original path in storage_key for later Restore. The parent_id is nulled so listings of the original parent forget the row.

Directories additionally drag their whole cached subtree along (GitHub issue #5): every live descendant row is rewritten to the matching trash-prefixed path (path_hash recomputed, original path preserved in storage_key) and soft-deleted. parent_id + name stay untouched on the children so RestoreNodeAt can mirror the rewrite back. Without this the children kept their ORIGINAL paths while soft-deleted, wedging the unique indexes for every future sync create at the same location.

func (*Store) SoftDeleteNode

func (s *Store) SoftDeleteNode(ctx context.Context, id int64) error

func (*Store) SoftDeleteNodeComment

func (s *Store) SoftDeleteNodeComment(ctx context.Context, id int64) error

SoftDeleteNodeComment flips deleted_at on a live comment.

func (*Store) StorageStats

func (s *Store) StorageStats(ctx context.Context, storageID int64) (int64, int64, error)

func (*Store) SumNodesBytesByStorage

func (s *Store) SumNodesBytesByStorage(ctx context.Context, storageID int64) (int64, error)

SumNodesBytesByStorage returns the total size in bytes of non-deleted files for one storage.

func (*Store) SumOpenStagedUploadBytes

func (s *Store) SumOpenStagedUploadBytes(ctx context.Context, userID int64) (int64, error)

func (*Store) TouchAPIToken

func (s *Store) TouchAPIToken(ctx context.Context, id int64) error

func (*Store) TouchLastLogin

func (s *Store) TouchLastLogin(ctx context.Context, id int64) error

func (*Store) TouchNFSExport

func (s *Store) TouchNFSExport(ctx context.Context, id int64) error

func (*Store) TouchNodeSeen

func (s *Store) TouchNodeSeen(ctx context.Context, id int64) error

func (*Store) TouchS3AccessKey

func (s *Store) TouchS3AccessKey(ctx context.Context, id int64) error

func (*Store) TouchSSHPublicKey

func (s *Store) TouchSSHPublicKey(ctx context.Context, id int64) error

func (*Store) UnlinkProviderStorage

func (s *Store) UnlinkProviderStorage(ctx context.Context, providerID, storageID int64) error

func (*Store) UnreadNotificationCount

func (s *Store) UnreadNotificationCount(ctx context.Context, userID *int64, mutedEvents, hiddenBodies []string, broadcasts model.BroadcastFilter) (int64, error)

UnreadNotificationCount returns the bell badge number for a user. Pass nil for the global unread count (admin dashboard).

func (*Store) UpdateAPITokenMeta

func (s *Store) UpdateAPITokenMeta(ctx context.Context, id int64, label, usernames, kind *string) error

UpdateAPITokenMeta edits label, the username allow-list and/or the token kind. nil = keep.

func (*Store) UpdateAppPlugin

func (s *Store) UpdateAppPlugin(ctx context.Context, p *model.AppPlugin) error

func (*Store) UpdateAppPluginJob

func (s *Store) UpdateAppPluginJob(ctx context.Context, j *model.AppPluginJob) error

func (*Store) UpdateChunkedUploadParts

func (s *Store) UpdateChunkedUploadParts(ctx context.Context, id string, parts []model.UploadPart) error

func (*Store) UpdateExternalServiceState

func (s *Store) UpdateExternalServiceState(ctx context.Context, name string, lastCheck time.Time, state string) error

func (*Store) UpdateFileGrantLevel

func (s *Store) UpdateFileGrantLevel(ctx context.Context, id int64, level string) error

func (*Store) UpdateNodeMeta

func (s *Store) UpdateNodeMeta(ctx context.Context, id int64, size int64, mime, etag string, mtime time.Time) error

func (*Store) UpdatePlugin

func (s *Store) UpdatePlugin(ctx context.Context, p *model.Plugin) error

func (*Store) UpdateProvider

func (s *Store) UpdateProvider(ctx context.Context, p *model.Provider) error

func (*Store) UpdateReplicaRule

func (s *Store) UpdateReplicaRule(ctx context.Context, id int64, in *model.ReplicaRuleInput) (*model.ReplicaRule, error)

UpdateReplicaRule replaces a rule's fields by id.

func (*Store) UpdateReplicationTarget

func (s *Store) UpdateReplicationTarget(ctx context.Context, rt *model.ReplicationTarget) error

func (*Store) UpdateShareAppState

func (s *Store) UpdateShareAppState(ctx context.Context, id int64, stateJSON string) error

UpdateShareAppState replaces the plugin's durable record for one link.

func (*Store) UpdateSharePinLock

func (s *Store) UpdateSharePinLock(ctx context.Context, id int64, fails int, until *time.Time) error

UpdateSharePinLock writes the strike counter and the lock deadline and NOTHING else — a wrong PIN must not be able to move an expiry or a cap by riding along in a whole-row save.

func (*Store) UpdateStagedUploadProgress

func (s *Store) UpdateStagedUploadProgress(ctx context.Context, id string, receivedBytes int64) error

func (*Store) UpdateStagedUploadState

func (s *Store) UpdateStagedUploadState(ctx context.Context, id, state, errMsg string) error

func (*Store) UpdateStorage

func (s *Store) UpdateStorage(ctx context.Context, st *model.Storage) error

func (*Store) UpdateStorageSyncCursor

func (s *Store) UpdateStorageSyncCursor(ctx context.Context, id int64, at time.Time, token string) error

func (*Store) UpdateUserAvatar

func (s *Store) UpdateUserAvatar(ctx context.Context, id int64, avatarURL string) error

UpdateUserAvatar stores (or, with an empty string, clears) the profile picture. Validation of the URI belongs to the API layer, which is the only place that knows what a browser will accept.

func (*Store) UpdateUserDisplayName

func (s *Store) UpdateUserDisplayName(ctx context.Context, id int64, displayName string) error

func (*Store) UpdateUserEmail

func (s *Store) UpdateUserEmail(ctx context.Context, id int64, email string) error

func (*Store) UpdateUserLocale

func (s *Store) UpdateUserLocale(ctx context.Context, id int64, locale, tz string) error

func (*Store) UpdateUserPassword

func (s *Store) UpdateUserPassword(ctx context.Context, id int64, hash string) error

func (*Store) UpdateUserRole

func (s *Store) UpdateUserRole(ctx context.Context, id int64, role string) error

func (*Store) UpdateWebhookStatus

func (s *Store) UpdateWebhookStatus(ctx context.Context, id int64, status, errMsg string) error

UpdateWebhookStatus is invoked by Service.Send after the HTTP attempt chain completes (or skips).

func (*Store) UpdateWebhookTarget

func (s *Store) UpdateWebhookTarget(ctx context.Context, t *model.WebhookTarget) error

UpdateWebhookTarget replaces the mutable columns of a target row.

func (*Store) UpdateWebhookTargetDelivery

func (s *Store) UpdateWebhookTargetDelivery(ctx context.Context, id int64, httpStatus int, errMsg string, at time.Time) error

UpdateWebhookTargetDelivery records the newest delivery outcome (migration 00019). errMsg "" (success) stores NULL in last_error.

func (*Store) UpsertCustomTheme

func (s *Store) UpsertCustomTheme(ctx context.Context, t *model.CustomTheme) error

UpsertCustomTheme creates or replaces a theme, keyed on its slug.

func (*Store) UpsertExternalService

func (s *Store) UpsertExternalService(ctx context.Context, name string, enabled bool, urlS, secretEnc, optionsJSON string, lastCheck time.Time, lastState string) error

func (*Store) UpsertNotificationSettings

func (s *Store) UpsertNotificationSettings(ctx context.Context, st *model.NotificationSettings) error

UpsertNotificationSettings stores the user's preferences.

func (*Store) UpsertReplicaFailure

func (s *Store) UpsertReplicaFailure(ctx context.Context, path, op, errCode, errMsg string) error

UpsertReplicaFailure either inserts a new failure or bumps attempts + last_attempt_at + the latest error code/message for the existing (path, op) row. Idempotent under retry.

func (*Store) UpsertReplicaSettings

func (s *Store) UpsertReplicaSettings(ctx context.Context, st *model.ReplicaSettings) error

UpsertReplicaSettings stores the singleton config row.

func (*Store) UpsertReplicaStatusReport

func (s *Store) UpsertReplicaStatusReport(ctx context.Context, total, failed, repaired int64, summaryJSON []byte) error

UpsertReplicaStatusReport replaces (id=1) the singleton report row.

func (*Store) UpsertSetting

func (s *Store) UpsertSetting(ctx context.Context, key, value string) error

func (*Store) UpsertThumbnail

func (s *Store) UpsertThumbnail(ctx context.Context, t *model.Thumbnail) error

func (*Store) WithTx added in v0.45.0

func (s *Store) WithTx(ctx context.Context, fn func(ctx context.Context) error) error

WithTx implements db.Store (see internal/db/tx.go).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL