database

package
v1.0.4 Latest Latest
Warning

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

Go to latest
Published: Jun 28, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

Documentation

Overview

Aether — GoStack Cassandra Wide-Column Database Integration Subsystem.

Purpose: This file implements the Aether Cassandra initialization helper for the GoStack framework. It establishes a gocql cluster session and verifies connectivity, returning the active *gocql.Session bound to the global gostack.Cassandra facade.

Philosophy: Aether surfaces the native gocql session directly. Cassandra operates on a distributed ring topology using the Cassandra Query Language (CQL), which maps naturally to Go's standard library patterns but differs fundamentally from both SQL and document paradigms. Wrapping it behind a SQL-shaped interface would prevent developers from using keyspace-aware queries, lightweight transactions (LWT), and Cassandra-specific consistency level controls.

Architecture: Aether sits in the database package and is only compiled into the binary when the developer explicitly selects Cassandra during project scaffolding, upholding GoStack's Modular Self-Containment principle.

Purpose: This file implements the Traveller database migration registry and runner.

Philosophy: Migrations are self-registering Go files. Each file calls database.Register() inside its init() function, which auto-executes when the package is imported. No manual wiring needed. The Migrator tracks completed migrations in a gostack_migrations table and runs only pending migrations, each wrapped in a database transaction.

Architecture: Part of the database package. The registry is a package-level slice. Migrator coordinates transaction-wrapped Up/Down execution and version tracking.

Choice: Consolidated migrate/migrator.go into database/migrator.go to keep all database operations in a single, cohesive package.

Implementation: - Migration: struct holding version, Up, and Down functions. - Register: self-registration entry point called from migration file init() functions. - Migrator: coordinates Run() and Rollback() against the DB.

GoMon — GoStack MongoDB Integration Subsystem.

Purpose: This file implements the GoMon MongoDB initialization helper for the GoStack framework. It exposes a *mongo.Client bound to the global gostack.Mongo facade after connecting and pinging the MongoDB server to verify the connection is alive.

Philosophy: GoMon does not wrap the MongoDB client behind a custom interface. Instead, it surfaces the official mongo.Client directly, giving developers full access to the native MongoDB Go driver API (collections, aggregations, transactions, change streams, etc.) without any limitations imposed by an intermediate wrapper layer.

Architecture: GoMon sits in the database package alongside the SQL adapter. It is only imported and compiled into the application binary when the developer explicitly selects MongoDB during project scaffolding. This upholds GoStack's Modular Self-Containment principle.

Nexus — GoStack Neo4j Graph Database Integration Subsystem.

Purpose: This file implements the Nexus Neo4j initialization helper for the GoStack framework. It establishes and verifies a Neo4j driver connection, returning the official neo4j.DriverWithContext bound to the global gostack.Neo4j facade.

Philosophy: Nexus surfaces the native Neo4j Go driver directly, giving developers full access to Cypher query execution, graph traversals, transactions, and bookmark management without any wrapper limitations. Graph databases have fundamentally different query patterns (Cypher vs SQL) and forcing them behind a SQL-shaped interface would severely restrict their capabilities.

Architecture: Nexus sits in the database package and is only compiled into the binary when the developer explicitly selects Neo4j during project scaffolding, upholding GoStack's Modular Self-Containment principle.

Purpose: This file contains the QueryBuilder struct and its associated chainable helper methods for constructing and executing relational SQL queries within the GoStack framework.

Philosophy: We believe query construction should be fluent, clean, and database-agnostic. By decoupling SQL compilation details (such as placeholder syntax) from application code, we empower developers to write standard SQL logic that is highly legible and testable.

Architecture: QueryBuilder tracks local query state (table, filters, bindings, eager relations) and delegates execution to an injected database client conforming to the contract.Database interface. Post-execution, result sets are directed to the hydration engine and relationships are eager-loaded.

Choice: We chose a direct, chainable builder style for its readability and simplicity. Rather than a heavily layered AST, we map clauses directly to query strings and bindings, providing a lightweight interface with minimal abstraction overhead.

Implementation: - QueryBuilder: manages table targets, filter state, placeholder index bindings, and relations. - New: instantiates a new builder with an injected database connector. - Where: appends AND filtering clauses with driver-specific placeholders. - WhereIn: appends WHERE IN clauses to avoid query duplication. - With: records relationships to be eager-loaded during hydration. - ToSQL: compiles internal state into an executable SQL string. - Execute: performs connection safety checks and executes the compiled query. - Get: coordinates query execution, cursor hydration, and eager relationship mapping.

Purpose: This file manages dynamic data translation, structural inspection, and relational row hydration for the GoStack framework ecosystem.

Philosophy: By leveraging Go's runtime reflection engine ('reflect'), this utility parses custom 'db' struct tags to reconcile data positioning. This allows the framework to populate data layouts without forcing developers to write manual, error-prone 'rows.Scan' loops for every entity model.

Architecture: It acts as the hydration helper functions within the database package.

Choice: Consolidated into the database package to avoid circular references and keep all mapping operations in a single package context.

Implementation: - Hydrate: inspects raw relational database rows and dynamically maps their column values. - mapRowToStruct: matches database columns with structural fields to assign values. - findFieldByTagName: matches database columns with struct tags or structural exact field name matches.

Purpose: This file implements the dynamic reflection-based ORM Relationship Management system for the GoStack framework. It currently supports eager loading for HasMany and BelongsTo relations.

Philosophy: We believe relationship loading should be convenient, transparent, and highly performant. Rather than inducing N+1 database querying loops, we batch load related entities using single sub-queries. We favor runtime structural tag analysis (db, rel, fk, table) to remain zero-dependency.

Architecture: Post-hydration, the query builder routes structural destination targets to the eager-loader. The loader inspects struct field definitions, queries children/owners using WhereIn sub-queries, and reflective maps hydrated relation structures back onto parent models using normalized key comparisons.

Choice: We chose runtime reflection over code generation to maximize developer ergonomics and avoid introducing CLI build steps into simple application templates.

Implementation: - eagerLoadRelations: root entry point that routes structs and slices to the slice-loader. - eagerLoadRelationForSlice: extracts field tags, defaults tables/keys, and triggers loading. - loadHasMany: eager loads HasMany relationships by mapping parent PKs to child FKs. - loadBelongsTo: eager loads BelongsTo relationships by mapping parent FKs to owner PKs. - findPrimaryKeyField: traverses fields to identify the struct's primary key name. - findFieldByDBTag: matches database column strings with struct field targets. - normalizeKey: coerces numeric and string kinds into comparable types for map lookup.

Purpose: This file implements the Grapher Schema Builder and Table DDL compiler for the GoStack framework. It provides a fluent, driver-aware API for defining and compiling CREATE TABLE and DROP TABLE statements.

Philosophy: Developers should never write raw DDL SQL. All schema definitions are expressed through type-safe Go method calls, allowing the framework to emit the correct SQL for each driver.

Architecture: Part of the database package. The Builder wraps a contract.Tx and dispatches DDL operations. The Table and Column types implement the fluent DSL for schema definition.

Choice: Consolidated schema/builder.go and schema/table.go into a single database/schema.go file to reduce package fragmentation and simplify imports.

Implementation: - ColumnKind: enumeration of supported column types. - Column: struct representing a single column definition with modifier chaining. - Table: struct holding an ordered list of Column definitions for a single table. - Builder: wraps contract.Tx to execute CREATE/DROP TABLE DDL atomically.

Purpose: This file implements the GoStack database seeding registry.

Philosophy: Seeding should be modular and easy to execute. By registering seeders via self-registering init() calls, we keep database population decoupled from the main CLI execution engine.

Architecture: Part of the database package. Seeders implement a simple Seeder interface and are invoked by the console db:seed command.

Purpose: This file implements standard SQL-based database operations, ensuring that the framework can communicate with relational databases like MySQL, PostgreSQL, or SQLite.

Philosophy: We believe relational database interactions should be clean, driver-agnostic, and secure. By wrapping standard library sql.DB pools, we provide a unified execution surface.

Architecture: Part of the database package, providing the driver implementation conforming to contract.Database.

Choice: Consolidated adapter, query, schema, and migrate into the database package to simplify database operations and remove circular dependencies.

Implementation: - SQLAdapter: struct wrapping sql.DB and tracking the driver string name. - NewSQLAdapter: constructor establishing standard database connection pools. - SQLTx: struct wrapping standard sql.Tx transactions.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func All

func All[T any](db contract.Database) ([]T, error)

All retrieves all records for the model type from the database.

func Create

func Create[T any](db contract.Database, fields map[string]any) (*T, error)

Create inserts a new record into the database and returns the populated struct.

func DeleteRecord

func DeleteRecord[T any](db contract.Database, id any) error

DeleteRecord deletes records matching the primary key id.

func Find

func Find[T any](db contract.Database, id any) (*T, error)

Find retrieves a single record from the database by primary key id.

func Hydrate

func Hydrate(rows *sql.Rows, dest any) error

Hydrate inspects raw relational database rows and dynamically maps their column values directly into a provided Go struct or slice pointer target.

func InitAether added in v1.0.1

func InitAether(hosts string, keyspace string) (*gocql.Session, error)

InitAether initializes and verifies a Cassandra connection using the provided cluster hosts and keyspace. It returns the connected *gocql.Session ready for use as the global gostack.Cassandra facade.

Parameters:

  • hosts: A comma-separated string of Cassandra cluster contact points (e.g. "127.0.0.1:9042").
  • keyspace: The Cassandra keyspace to bind the session to (e.g. "myapp").

Returns:

  • A live *gocql.Session, or an error if the cluster connection or session creation fails.

func InitGoMon added in v1.0.1

func InitGoMon(uri string) (*mongo.Client, error)

InitGoMon initializes and verifies a MongoDB connection using the provided URI. It returns the connected *mongo.Client ready for use as the global gostack.Mongo facade.

Parameters:

  • uri: The MongoDB connection string (e.g. "mongodb://127.0.0.1:27017").

Returns:

  • A live *mongo.Client, or an error if connection or ping fails.

func InitNexus added in v1.0.1

func InitNexus(uri, username, password string) (neo4j.DriverWithContext, error)

InitNexus initializes and verifies a Neo4j connection using the provided URI and credentials. It returns the connected neo4j.DriverWithContext ready for use as the global gostack.Neo4j facade.

Parameters:

  • uri: The Neo4j connection URI (e.g. "neo4j://localhost:7687" or "neo4j+s://..." for AuraDB).
  • username: The Neo4j authentication username (typically "neo4j").
  • password: The Neo4j authentication password.

Returns:

  • A live neo4j.DriverWithContext, or an error if connection or verification fails.

func Register

func Register(version int64, up, down func(s *Builder) error)

Register adds a new migration to the global registry. Designed to be called from the init() function of each migration file.

func RegisterSeeder

func RegisterSeeder(name string, s Seeder)

RegisterSeeder adds a seeder to the global registry. Typically called from init() in generated seeder files.

func RunAllSeeders

func RunAllSeeders() error

RunAllSeeders runs all registered seeders. If "DatabaseSeeder" exists, it runs only DatabaseSeeder. Otherwise, it runs all registered seeders.

func RunSeeder

func RunSeeder(name string) error

RunSeeder runs a single seeder by name.

func Update

func Update[T any](db contract.Database, id any, fields map[string]any) error

Update updates records matching the primary key id.

Types

type AfterCreator

type AfterCreator interface {
	AfterCreate() error
}

AfterCreator is implemented by models that need to run logic after a successful INSERT.

type AfterDeleter

type AfterDeleter interface {
	AfterDelete() error
}

AfterDeleter is implemented by models that need to run logic after a successful DELETE.

type BeforeDeleter

type BeforeDeleter interface {
	BeforeDelete() error
}

BeforeDeleter is implemented by models that need to run logic before a DELETE.

type BeforeSaver

type BeforeSaver interface {
	BeforeSave() error
}

BeforeSaver is implemented by models that need to run logic before any INSERT or UPDATE.

type Builder

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

Builder wraps a contract.Tx to execute DDL operations atomically within a database transaction.

func NewBuilder

func NewBuilder(tx contract.Tx, driver string) *Builder

NewBuilder constructs a Schema Builder bound to an active transaction and a driver name.

func (*Builder) Create

func (b *Builder) Create(tableName string, fn func(*Table)) error

Create compiles and executes a CREATE TABLE statement.

func (*Builder) Drop

func (b *Builder) Drop(tableName string) error

Drop executes a DROP TABLE IF EXISTS statement for the given table name.

type Column

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

Column represents a single database column definition.

func (*Column) Default

func (c *Column) Default(val any) *Column

Default sets a default value for this column.

func (*Column) Nullable

func (c *Column) Nullable() *Column

Nullable marks this column as allowing NULL values.

func (*Column) Unique

func (c *Column) Unique() *Column

Unique adds a UNIQUE constraint to this column.

type ColumnKind

type ColumnKind int

ColumnKind identifies the semantic data category of a column definition.

const (
	KindID        ColumnKind = iota // Auto-increment primary key
	KindString                      // VARCHAR(255)
	KindInteger                     // INT
	KindBoolean                     // TINYINT(1) / BOOLEAN
	KindText                        // TEXT
	KindTimestamp                   // DATETIME / TIMESTAMPTZ
)

type Migration

type Migration struct {
	// Version is a unique integer identifier (e.g. 20260612001, sortable by creation time).
	Version int64

	// Up defines the forward schema change using the GoStack Schema Builder.
	Up func(s *Builder) error

	// Down defines the rollback schema change to reverse the Up operation.
	Down func(s *Builder) error
}

Migration represents a single versioned schema change with Up and Down functions.

type Migrator

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

Migrator coordinates running and rolling back database migrations.

func NewMigrator

func NewMigrator(db contract.Database) *Migrator

NewMigrator constructs a Migrator bound to an active database connection.

func (*Migrator) Rollback

func (m *Migrator) Rollback() error

Rollback reverses the last single migration in descending version order.

func (*Migrator) Run

func (m *Migrator) Run() error

Run executes all pending migrations in ascending version order.

type Model

type Model interface {
	TableName() string
}

Model defines an optional interface for custom database table name mapping.

type PageMeta

type PageMeta struct {
	Total    int  `json:"total"`
	Page     int  `json:"page"`
	PerPage  int  `json:"per_page"`
	LastPage int  `json:"last_page"`
	HasNext  bool `json:"has_next"`
	HasPrev  bool `json:"has_prev"`
}

PageMeta stores structural pagination attributes for API response formatting.

type QueryBuilder

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

QueryBuilder serves as the core state manager for SQL construction.

func New

func New(db contract.Database, table string) *QueryBuilder

New constructs a new QueryBuilder instance.

func (*QueryBuilder) Count

func (qb *QueryBuilder) Count() (int, error)

Count returns the total number of records matching current query constraints.

func (*QueryBuilder) Delete

func (qb *QueryBuilder) Delete() error

Delete compiles and executes a DELETE statement against the target table. Fires BeforeDelete and AfterDelete hooks on model if provided via DeleteModel.

Example:

gostack.Table("users").Where("id", "=", 42).Delete()

func (*QueryBuilder) DeleteModel

func (qb *QueryBuilder) DeleteModel(model any) error

DeleteModel is Delete with optional model hook support.

func (*QueryBuilder) Execute

func (qb *QueryBuilder) Execute() (any, error)

Execute triggers the execution of the built SQL query via the injected database connection.

func (*QueryBuilder) First

func (qb *QueryBuilder) First(dest any) error

First executes the query with LIMIT 1 and hydrates the result into dest, which should be a pointer to a struct (not a slice). Returns an error wrapping ErrNoRows if no record is found.

Example:

var user model.User
err := gostack.Table("users").Where("email", "=", email).First(&user)

func (*QueryBuilder) Get

func (qb *QueryBuilder) Get(dest any) error

Get executes the compiled query and automatically hydates the database results directly into the provided destination pointer (struct or slice of structs).

func (*QueryBuilder) Insert

func (qb *QueryBuilder) Insert(data map[string]any) error

Insert compiles and executes an INSERT DDL operation against the target table. It fires BeforeSave() before execution and AfterCreate() after a successful insert.

func (*QueryBuilder) InsertModel

func (qb *QueryBuilder) InsertModel(model any, data map[string]any) error

InsertModel is Insert with optional model hook support. Pass the model pointer to enable BeforeSave and AfterCreate lifecycle hooks.

func (*QueryBuilder) Limit

func (qb *QueryBuilder) Limit(n int) *QueryBuilder

Limit caps the number of rows returned.

Example:

gostack.Table("posts").Limit(10).Get(&posts)

func (*QueryBuilder) Offset

func (qb *QueryBuilder) Offset(n int) *QueryBuilder

Offset skips the first n rows before returning results.

Example:

gostack.Table("posts").Limit(10).Offset(20).Get(&posts)

func (*QueryBuilder) OrderBy

func (qb *QueryBuilder) OrderBy(col, dir string) *QueryBuilder

OrderBy appends an ORDER BY clause to the query. dir should be "ASC" or "DESC".

Example:

gostack.Table("posts").OrderBy("created_at", "DESC").Get(&posts)

func (*QueryBuilder) Paginate

func (qb *QueryBuilder) Paginate(dest any, page, perPage int) (*PageMeta, error)

Paginate counts total records matching current query conditions, retrieves the requested chunk of rows for the target page, and hydrates them into dest.

func (*QueryBuilder) ToSQL

func (qb *QueryBuilder) ToSQL() string

ToSQL serializes the internal state into a valid SQL query string.

func (*QueryBuilder) Update

func (qb *QueryBuilder) Update(data map[string]any) error

Update compiles and executes an UPDATE statement against the target table. Fires BeforeSave hook on model if provided via UpdateModel.

Example:

gostack.Table("users").Where("id", "=", 1).Update(map[string]any{"name": "Alice"})

func (*QueryBuilder) UpdateModel

func (qb *QueryBuilder) UpdateModel(model any, data map[string]any) error

UpdateModel is Update with optional model hook support.

func (*QueryBuilder) Where

func (qb *QueryBuilder) Where(col, op string, val any) *QueryBuilder

Where adds a filtering condition to the internal state.

func (*QueryBuilder) WhereIn

func (qb *QueryBuilder) WhereIn(col string, vals []any) *QueryBuilder

WhereIn adds a "WHERE col IN (?, ?, ...)" clause to the query state.

func (*QueryBuilder) With

func (qb *QueryBuilder) With(relations ...string) *QueryBuilder

With specifies one or more relationships to be eager-loaded with the query results.

type SQLAdapter

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

SQLAdapter is the concrete implementation of the contract.Database interface.

func NewSQLAdapter

func NewSQLAdapter(driver, dsn string) (*SQLAdapter, error)

NewSQLAdapter acts as a constructor for the SQLAdapter.

func (*SQLAdapter) BeginTx

func (a *SQLAdapter) BeginTx() (contract.Tx, error)

BeginTx opens a new database transaction and returns it wrapped in the contract.Tx interface.

func (*SQLAdapter) Close added in v1.0.1

func (a *SQLAdapter) Close() error

Close releases the underlying SQL database connection pool.

func (*SQLAdapter) Connect

func (a *SQLAdapter) Connect() error

Connect verifies that the database connection is alive by performing a Ping.

func (*SQLAdapter) Driver

func (a *SQLAdapter) Driver() string

Driver returns the database driver identifier name.

func (*SQLAdapter) Exec

func (a *SQLAdapter) Exec(sqlString string, args ...any) error

Exec executes a SQL statement that returns no rows (DDL, INSERT, UPDATE, DELETE).

func (*SQLAdapter) Query

func (a *SQLAdapter) Query(sqlString string, args ...any) (any, error)

Query executes the provided SQL query with parameters and returns the result set.

type SQLTx

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

SQLTx wraps a standard *sql.Tx to implement the contract.Tx interface.

func (*SQLTx) Commit

func (t *SQLTx) Commit() error

Commit finalizes the transaction.

func (*SQLTx) Exec

func (t *SQLTx) Exec(sqlString string, args ...any) error

Exec executes a parameterized SQL statement inside the transaction.

func (*SQLTx) Query

func (t *SQLTx) Query(sqlString string, args ...any) (any, error)

Query executes a parameterized SQL query inside the transaction.

func (*SQLTx) Rollback

func (t *SQLTx) Rollback() error

Rollback aborts the transaction.

type Seeder

type Seeder interface {
	Run() error
}

Seeder defines the contract for populating database tables with seed data.

type Table

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

Table holds the full ordered list of column definitions for a CREATE TABLE statement.

func NewTable

func NewTable(driver string) *Table

NewTable constructs a fresh Table definition bound to a specific driver.

func (*Table) Boolean

func (t *Table) Boolean(name string) *Column

Boolean appends a BOOLEAN column.

func (*Table) Compile

func (t *Table) Compile(tableName string) string

Compile translates the full column list into a driver-aware CREATE TABLE SQL string.

func (*Table) ID

func (t *Table) ID() *Column

ID appends a driver-aware auto-incrementing primary key column.

func (*Table) Integer

func (t *Table) Integer(name string) *Column

Integer appends an INTEGER column.

func (*Table) String

func (t *Table) String(name string) *Column

String appends a VARCHAR(255) column.

func (*Table) Text

func (t *Table) Text(name string) *Column

Text appends a TEXT column.

func (*Table) Timestamp

func (t *Table) Timestamp(name string) *Column

Timestamp appends a TIMESTAMP / DATETIME column.

func (*Table) Timestamps

func (t *Table) Timestamps()

Timestamps appends the standard created_at and updated_at columns.

Jump to

Keyboard shortcuts

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