sqlfilestore

package module
v1.1.0 Latest Latest
Warning

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

Go to latest
Published: Nov 21, 2025 License: GPL-3.0 Imports: 13 Imported by: 1

README

SQL File Store

Open in Gitpod

tests Go Report Card PkgGoDev

SQL File Store persists a hierarchical file-system-like structure in a relational database. It handles record creation, querying, soft deletion, and path recalculation for nested directories and files, while keeping a root directory available out of the box.

Features

  • Automatic schema creation (automigration) with a configurable table name.
  • Strongly typed Record helper with builders for files and directories.
  • CRUD helpers: create, update, hard delete, soft delete, and list with filtering options.
  • Recursive path recalculation to keep child paths in sync with renamed parents.
  • Works with standard database/sql connections and supports multiple SQL drivers through query builders.

Installation

go get github.com/dracory/sqlfilestore

Quick Start

package main

import (
    "database/sql"

    "github.com/dracory/sqlfilestore"
    _ "modernc.org/sqlite" // driver
)

func main() {
    db, _ := sql.Open("sqlite", ":memory:?parseTime=true")

    store, err := sqlfilestore.NewStore(sqlfilestore.NewStoreOptions{
        DB:                 db,
        TableName:          "file_records",
        AutomigrateEnabled: true,
    })
    if err != nil {
        panic(err)
    }

    file := sqlfilestore.NewFile().
        SetParentID(sqlfilestore.ROOT_ID).
        SetName("example.txt").
        SetPath("/example.txt").
        SetExtension("txt").
        SetContents("Hello, world!")

    if err := store.RecordCreate(file); err != nil {
        panic(err)
    }
}

The example mirrors the test setup used for the in-memory SQLite driver.

Working with Records

All records share a common Record model. File and directory helpers pre-configure type-specific fields:

  • NewDirectory() sets type to directory, zeroes size, and clears file-only fields.
  • NewFile() sets type to file and leaves contents configurable.
  • NewRecord() creates a bare record with generated ID and timestamps.

Each record exposes setters/getters for metadata including name, path, parent ID, file size, extension, and timestamps.

Creating Directories
dir := sqlfilestore.NewDirectory().
    SetParentID(sqlfilestore.ROOT_ID).
    SetName("docs").
    SetPath("/docs")

if err := store.RecordCreate(dir); err != nil {
    // handle error
}
Updating Paths

Rename operations require updating the stored path. Use RecordRecalculatePath to refresh a record and its descendants after changing the name.

dir.SetName("manuals")
if err := store.RecordUpdate(dir); err == nil {
    _ = store.RecordRecalculatePath(dir, nil)
}

Querying Data

RecordQueryOptions lets you filter by ID, parent, type, path, timestamps, and sorting options.

records, err := store.RecordList(sqlfilestore.RecordQueryOptions{
    ParentID: sqlfilestore.ROOT_ID,
    Type:     sqlfilestore.TYPE_FILE,
    OrderBy:  "created_at",
    SortOrder: "asc",
})

Use RecordFindByID and RecordFindByPath for single-record lookups.

Soft Deletes vs. Hard Deletes

  • RecordSoftDeleteByID keeps the record while setting deleted_at for reversible removals.
  • RecordDeleteByID permanently removes a record, ensuring directories are empty beforehand.

Soft-deleted records are excluded by default; enable WithSoftDeleted in query options to include them.

Debugging

Enable SQL logging with store.EnableDebug(true) to print generated statements before execution.

Running Tests

The repository includes comprehensive tests that demonstrate typical interactions with the store.

go test ./...

License

GPL-3.0. See LICENSE.

Documentation

Index

Constants

View Source
const COLUMN_CONTENTS = "contents"
View Source
const COLUMN_CREATED_AT = "created_at"
View Source
const COLUMN_DELETED_AT = "deleted_at"
View Source
const COLUMN_EXTENSION = "extension"
View Source
const COLUMN_ID = "id"
View Source
const COLUMN_NAME = "name"
View Source
const COLUMN_PARENT_ID = "parent_id"
View Source
const COLUMN_PATH = "path"
View Source
const COLUMN_SIZE = "size"
View Source
const COLUMN_TYPE = "type"
View Source
const COLUMN_UPDATED_AT = "updated_at"
View Source
const PATH_SEPARATOR = "/"
View Source
const ROOT_ID = "0"
View Source
const ROOT_PATH = PATH_SEPARATOR
View Source
const TYPE_DIRECTORY = "directory"
View Source
const TYPE_FILE = "file"

Variables

This section is empty.

Functions

This section is empty.

Types

type NewStoreOptions

type NewStoreOptions struct {
	TableName          string
	DB                 *sql.DB
	DbDriverName       string
	AutomigrateEnabled bool
	DebugEnabled       bool
}

NewStoreOptions define the options for creating a new block store

type Record

type Record struct {
	dataobject.DataObject
}

func NewDirectory

func NewDirectory() *Record

func NewFile

func NewFile() *Record

func NewRecord

func NewRecord() *Record

func NewRecordFromExistingData

func NewRecordFromExistingData(data map[string]string) *Record

func (*Record) Contents

func (o *Record) Contents() string

func (*Record) CreatedAt

func (o *Record) CreatedAt() string

func (*Record) DeletedAt

func (o *Record) DeletedAt() string

func (*Record) Extension

func (o *Record) Extension() string

func (*Record) ID

func (o *Record) ID() string

func (*Record) IsDirectory

func (o *Record) IsDirectory() bool

func (*Record) IsFile

func (o *Record) IsFile() bool

func (*Record) Name

func (o *Record) Name() string

func (*Record) ParentID

func (o *Record) ParentID() string

func (*Record) Path

func (o *Record) Path() string

func (*Record) SetContents

func (o *Record) SetContents(fileContents string) *Record

func (*Record) SetCreatedAt

func (o *Record) SetCreatedAt(createdAt string) *Record

func (*Record) SetDeletedAt

func (o *Record) SetDeletedAt(deletedAt string) *Record

func (*Record) SetExtension

func (o *Record) SetExtension(extension string) *Record

func (*Record) SetID

func (o *Record) SetID(id string) *Record

func (*Record) SetName

func (o *Record) SetName(name string) *Record

func (*Record) SetParentID

func (o *Record) SetParentID(parentID string) *Record

func (*Record) SetPath

func (o *Record) SetPath(filePath string) *Record

SetPath sets the file path. As all paths must start with "/" adds a "/" if not present. Any trailing spaces is also trimmed

func (*Record) SetSize

func (o *Record) SetSize(fileSize string) *Record

func (*Record) SetType

func (o *Record) SetType(fileType string) *Record

func (*Record) SetUpdatedAt

func (o *Record) SetUpdatedAt(updatedAt string) *Record

func (*Record) Size

func (o *Record) Size() string

func (*Record) Type

func (o *Record) Type() string

func (*Record) UpdatedAt

func (o *Record) UpdatedAt() string

type RecordQueryOptions

type RecordQueryOptions struct {
	ID                   string
	IDIn                 []string
	ParentID             string
	Type                 string
	Path                 string
	PathStartsWith       string
	CreatedAtLessThan    string
	CreatedAtGreaterThan string
	UpdatedAtLessThan    string
	UpdatedAtGreaterThan string
	Columns              []string
	Offset               int
	Limit                int
	SortOrder            string
	OrderBy              string
	CountOnly            bool
	WithSoftDeleted      bool
}

type Store

type Store struct {
	// contains filtered or unexported fields
}

func NewStore

func NewStore(opts NewStoreOptions) (*Store, error)

NewStore creates a new block store

func (*Store) AutoMigrate

func (store *Store) AutoMigrate(ctx context.Context) error

AutoMigrate auto migrate

func (*Store) EnableDebug

func (st *Store) EnableDebug(debug bool)

EnableDebug - enables the debug option

func (*Store) RecordCount

func (st *Store) RecordCount(ctx context.Context, options RecordQueryOptions) (int64, error)

func (*Store) RecordCreate

func (store *Store) RecordCreate(ctx context.Context, record *Record) error

func (*Store) RecordDelete

func (store *Store) RecordDelete(ctx context.Context, record *Record) error

func (*Store) RecordDeleteByID

func (store *Store) RecordDeleteByID(ctx context.Context, id string) error

func (*Store) RecordFindByID

func (store *Store) RecordFindByID(ctx context.Context, id string, options RecordQueryOptions) (*Record, error)

func (*Store) RecordFindByPath

func (store *Store) RecordFindByPath(ctx context.Context, path string, options RecordQueryOptions) (*Record, error)

func (*Store) RecordList

func (store *Store) RecordList(ctx context.Context, options RecordQueryOptions) ([]Record, error)

func (*Store) RecordRecalculatePath

func (store *Store) RecordRecalculatePath(ctx context.Context, record *Record, parentRecord *Record) error

func (*Store) RecordSoftDelete

func (store *Store) RecordSoftDelete(ctx context.Context, record *Record) error

func (*Store) RecordSoftDeleteByID

func (store *Store) RecordSoftDeleteByID(ctx context.Context, id string) error

func (*Store) RecordUpdate

func (store *Store) RecordUpdate(ctx context.Context, record *Record) error

Jump to

Keyboard shortcuts

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