datarepo

package module
v0.0.0-...-4b2a5ba Latest Latest
Warning

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

Go to latest
Published: Apr 22, 2025 License: MIT Imports: 11 Imported by: 2

README

datarepo

Prototype of an all-weather all-terrain data repository for Go, defaulting to SQLite.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var DEFAULT_FILENAME = "m5.db"

Functions

This section is empty.

Types

type AppTableSetter

type AppTableSetter interface {
	// RegisterAppTables processes the schemata of the specified
	// app's tables, which this interface creates and/or manages.
	//  - Multiple calls to this func do not conflict, whether
	//    with tables previously specified or not before seen
	//  - If a table name is repeated but with a different schema,
	//    the result is undefined
	//  - If the tables already exist in the DB, it is not verified
	//    that their structure matches what this schema specifies
	//    (but this might be a future TODO)
	RegisterAppTables(string, []*DRM.TableDetails) error
	// EmptyAllTables deletes (app-level) data from the app's tables
	// but does not delete any tables (i.e. no DROP TABLE are done).
	EmptyAppTables() error
	// CreateTables creates the app's tables per already-supplied
	// schema(ta); if the tables exist, they are emptied of data.
	CreateAppTables() error
}

AppTableSetter is table-related methods for a specified app's schema.

An untested feature is that an app name prefix can be added, via the first argument to func [RegisterAppTables]. The app name is case-insensitive, and used as all lower case, and prefixed to table names as "appname_". If the app name is left blank (""), a default namespace is used and no prefix is added to table names. .

type Backupable

type Backupable interface {
	MoveToBackup() (string, error)
	CopyToBackup() (string, error)
	RestoreFromMostRecentBackup() (string, error)
}

Backupable methods are invoked directly by the DB implementation being backed up, rather than by some sort of high-level "Manager". The methods work with locations, whose type (filepath, dir path, or URI/URL) and naming convention (including date & time) are determined by the implementation for each DB. Methods exist to move DB to, copy DB to, or restore DB from a location. Each method returns a location: the new backup or restored-from backup.

There are equivalent sqlite3 commands at the CLI:

  • sqlite3 my_database.db ".backup 'backup_file.db'"
  • sqlite3 my_database.db ".backup m_database.db.bak"
  • sqlite3 my_database .backup > my_database.back

.

type Caller

type Caller[T DRM.RowModel] interface {
	BeginImmed() error
	DoSelectByIdGeneric(SimpleRepo, int, T) (bool, error)
	DoInsertGeneric(SimpleRepo, T) (int, error)
}

Caller methods are a temp list.

type DBEnginer

type DBEnginer interface {
	// EngineUnique works on/with a single DB record.
	EngineUnique(dbOp string, tableName string,
		anID int, RM DRM.RowModel) (int, error)
}

DBEnginer is TBS.

type DBManager

type DBManager interface {
	OpenAtPath(string) (SimpleRepo, error)
	NewAtPath(string) (SimpleRepo, error)
	OpenExistingAtPath(string) (SimpleRepo, error)
	// InitznPragmas is assumed to be multiline
	InitznPragmas() string
	// ReadonlyPragma is assumed to be a single pragma
	// that returns some sort of status message
	ReadonlyPragma() string
}

DBManager has methods to create, open, and configure databases.

NOTE: The recommended action is to call OpenAtPath, which then selects one of the other two. .

var DB_Manager DBManager

DB_Manager is a global, maybe for SQLite, maybe for ebberyting. It probably needs some sort of mutex.

type Entity

type Entity interface {
	// Handle (noun) is the handle to the DB.
	Handle() *sql.DB
	// Type has value [dsmnd.DB_SQLite] ("sqlite", equiv.to "sqlite3").
	Type() D.DB_type
	// Path is the file/URL (or dir/URL, if uses multiple files) to the DB.
	Path() string
	// IsURL is false for a local SQLite file.
	IsURL() bool
	// IsSingleFile is true for SQLite.
	IsSingleFile() bool
}

Entity provides operations for database entities (i.e. instances).

type FieldValuePair

type FieldValuePair struct {
	Field string
	Value string
}

UniquerySpec specifies a query that keys on equality for a UNIQUE column.

Field [Value] is passed as a string, n0 matter what type column [Field] is. This is kind of dodgy, but since we are only really using strings and ints, it should not cause any breakage.

2025.02: Generics were tried for field [Value] with the constraint "comparable". Then instantiation required that we provide the Go type of the keyed-on column `keyT`, e.g. `UniquerySpec[int]`. But it got too messy, so instead the field [FVtype] is used to keep things typesafe going into and out of the DB.

In principle the keyed-on column can be any UNIQUE column, but the most common case is

  • column name `ID` (or `{TBL}_ID`)
  • Go type `int`
  • SQL type `INT`/`INTEGER` ([dsmnd.SQLITE_INTEGER])

For DBOp we can/could have

  • sql INSERT / crud CREATE / http POST / "Add" (pass in a record, get an ID)
  • sql SELECT / crud RETRIV / http GET / "Get" (return a record)
  • sql UPDATE / crud UPDATE / http PUT / "Mod" (pass in a record)
  • sql DELETE / crud DELETE / http DEL. / "Del" (beware: FKey issues)

An error should be returned only if the SQL was rejected. If the unique row is not found, return a nil object and no error.

This is meant to be passed to a query composer (not "builder") that is specific to a DB. Which means, for now, SQLite.

DBOp should probably be defined in package dsmnd. . typ UniquerySpec struct { // [keyT comparable] struct {

type GenericRepo

type GenericRepo[T any] interface {
	Create(T) T
	GetAll() []T
	GetByID(uint) (T, error)
	UpdateByID(uint, T) (T, error)
	DeleteByID(uint) (bool, error)
	GetSome(string) []T
}

type Init9nArgs

type Init9nArgs struct {
	// D.DB_type is so far only D.DB_SQLite = "sqlite"
	D.DB_type
	// BaseFilename defaults to "m5.db"
	BaseFilename string
	Dir          string

	// DoImport requires DB access, so it is present
	// here, but it is not otherwise processed here.
	DoImport bool
	// DoZeroOut says initialize the DB with the
	// app's tables but with no data in them
	DoZeroOut bool
	// DoBackup says before DoingZeroOut on an
	// existing DB, first copy it to a backup
	// copy using a hard-coded naming scheme
	DoBackup bool
	// TableDetailz are app tables' details
	TableDetailz []*DRM.TableDetails
}

Init9nArgs is for database management. Note that if field [UseDB] is false, the contents and usage of this struct are undefined.

func (*Init9nArgs) ProcessInit9nArgs

func (p *Init9nArgs) ProcessInit9nArgs() (SimpleRepo, error)

ProcessInit9nArgs processes DN initialization arguments. It can process either a new DB OR an existing DB.

If the returned error is non-nil, it need not be fatal. Check whether the SimpleRepo return value is nil.

TODO: It should not use a complex logger (e.g. [mlog]), because we want to avoid that kind of dependency in a standalone library. .

type QuerySpec

type QuerySpec struct {
	DBOp  string
	Table string
	Id1   int
	IdN   []int
	IsAnd bool // Irrelevant when only one condition
	// Conditions is AND-or-OR of (e.g.)
	// { FieldName, "<= Zork" } .
	// For SELECT, is a map[string]nils
	Conditions map[string]string
}

QuerySpec specifies a cross-DB query.

Id1 and IdN should be mutually exclusive, such that if IdN is nil or len==0 then Id1 governs. Similarly(?), fetch "ALL" could be indicated by Id1 set to -1.

This does not handle a list of values to be equal to, except for multiple IDs (passed in as [IdN]).

DBOp should probably be defined in package [dsmnd]. .

type SessionLifecycler

type SessionLifecycler interface {
	// Open is called on an existing repo file, and can be called
	// multiple times in a sessions, so it should not do pragma-style
	// initialization; however, options passed in the connection
	// string (such as SQLite's "...?foreign_keys=on") are kosher.
	Open() error
	SetLogWriter(io.Writer) io.Writer
	// DoPragmas is provided mainly for use in initialization,
	// but it is not included by default in any other functions
	// in this interface because of variations in usage of pragmas.
	// It is the therefore the sole responsibility of a caller to
	// determine which pragmas(s) to execute, and when.
	DoPragmas(string) (string, error)
	// IsOpen also pings the DB as a health check.
	IsOpen() bool
	// Verify runs app-level sanity & consistency checks (but things
	// like foreign key integtrity should be delegated to DB setup).
	Verify() error
	Flush() error
	// Close remembers the path (like [os.File] does).
	Close() error
	CloseLogWriter()
}

SessionLifecycler is session lifecycle operations for databases. The database is treated as stateful.

type SimpleRepo

type SimpleRepo interface {
	// Entity is the Repo's basics: type, path, etc.
	Entity
	// Backupable is copy, move, restoreFrom
	Backupable
	// SessionLifecycler is open, close, etc.
	SessionLifecycler
	// StatementBuilder uses [TableDescriptor] and [QuerySpec]
	StatementBuilder

	// AppTableSetter is table mgmt for a specific Repo-using app.
	AppTableSetter
	// DBEnginer is basic DB ops.
	DBEnginer
	LogWriter() io.Writer
}

SimpleRepo is an interface that combines several other interfaces, and can be fully specified by

  1. an implementation, currently limited to [dsmnd.DB_SQLite] ("sqlite"), plus
  2. a filepath or a URL, for opening or creating, which may be either relative or absolute

Each field in the struct is tipicly a ptr, and tipicly they all point to the same single object.

A SimpleRepo is expected to implement DBBackups. .

type StatementBuilder

type StatementBuilder interface {
	// BuildQueryStmt(*DRU.QuerySpec) (string, error)
	NewCreateTableStmt(*DRM.TableDetails) (string, error)
}

StatementBuilder is DB-specific and implemented by *[sqlite.SqliteRepo]

type StatementBuilder_generics

type StatementBuilder_generics[T DRM.RowModel] interface {
	// BuildQueryStmt(*DRU.QuerySpec) (string, error)
	NewCreateTableStmt(T) (string, error)
	NewSelectByIdStmt(T, int) (string, error)
}

StatementBuilder_generics is DB-specific and implemented by *[sqlite.SqliteRepo]

Directories

Path Synopsis
Package sqlite provides func specific to SQLite-based implementations¨ of package [repo].
Package sqlite provides func specific to SQLite-based implementations¨ of package [repo].
Package utils provides utility types and funcs for packages [datarepo] and [sqlite].
Package utils provides utility types and funcs for packages [datarepo] and [sqlite].

Jump to

Keyboard shortcuts

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