Skip to content
Lemon4ksanPublic

About

🌅 The zero-allocation data access substrate and protocol driver engine for Go

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

4 Commits

Folders and files

Repository files navigation

dawn

The Zero-Allocation Data Access Substrate & Protocol Driver Engine for Go

«In databases, darkness is the default — let dawn break the night»

Go Version Go Reference License Zero-Alloc Ecosystem

dawn is a high-performance database protocol driver engine and zero-allocation data access substrate for Go. It provides direct struct memory mapping without runtime reflection, 1-RTT query pipelining, cross-dialect fluent query builders, a zero-allocation ORM, and low-level protocol bricks for database driver authors.

English • Русский

Installation

dawn requires Go version 1.27 or higher.

go get github.com/lemon4ksan/dawn

Quickstart

Direct query execution with compile-time struct memory offsets:

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/lemon4ksan/dawn"
	"github.com/lemon4ksan/dawn/types"
)

type User struct {
	ID       int64              `db:"id,pk"`
	Username types.CompactString `db:"username"`
	Email    string             `db:"email"`
	Location types.Point        `db:"location"`
	IsActive bool               `db:"is_active"`
}

func main() {
	ctx := context.Background()

	client, err := dawn.Open("postgres://postgres:secret@localhost:5432/app",
		dawn.WithMaxOpenConns(32),
		dawn.WithAutoPipelining(true),
	)
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()

	// 1. Single row query (direct memory mapping, 0 B/op)
	user, err := dawn.QueryOne[User](ctx, client,
		"SELECT id, username, email, location, is_active FROM users WHERE id = $1", 42,
	)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("User: %s (Location: %s)\n", user.Username.String(), user.Location.String())

	// 2. Slice query
	users, err := dawn.QueryInto[User](ctx, client,
		"SELECT id, username, email, location, is_active FROM users WHERE is_active = true LIMIT 50",
	)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("Fetched %d active users\n", len(users))

	// 3. Streaming row iterator (iter.Seq2[User, error])
	for u, err := range client.QueryIter[User](ctx, "SELECT id, username, email, location, is_active FROM users") {
		if err != nil {
			log.Fatal(err)
		}
		_ = u
	}
}

Architecture & Substrates

dawn is decomposed into sovereign, zero-dependency subpackages:

Package Purpose Performance
dawn/schema Precompiled struct memory offsets (uintptr) and direct DTO streaming 0 B/op, 0 reflect
dawn/builder Fluent cross-dialect SQL query builder with zero-alloc Core brick 49.5 ns/op, 0 B/op
dawn/orm Zero-allocation typed ORM repository and model queries 100.8 ns/op, 0 B/op
dawn/codegen SQL-to-Go code generator producing typed models without rows.Scan Standalone / sqlc
dawn/types Hardware types (CompactString, ValidityMask, Point, ColumnVector) 0.28–0.58 ns/op
dawn/wire CompositeBuffer (writev), BackpatchWriter, and Varint decoders 0.48–19.9 ns/op, 0 B/op
dawn/pipeline FastLock, CancelRegistry, TxController, Cursor, and Batcher 1.71 ns/op, 0 B/op
dawn/storage 4KB Slotted Page layout and lock-free Copy-on-Write MVCC B+Tree 12.8–14.7 ns/op, 0 B/op
dawn/driver/pg Pure-Go 1-RTT PostgreSQL wire driver with SCRAM-SHA-256 Zero-copy streaming
dawn/driver/sqlite Embedded zero-allocation SQLite engine and VDBE runner In-memory transactions

Fluent Query Builder

Composable SQL expressions with support for PostgreSQL ($1), MySQL (?), SQLite, ClickHouse, and DuckDB:

import "github.com/lemon4ksan/dawn/builder"

// SELECT with JOIN, WHERE conditions, and Dialect pagination
sql, args := builder.NewSelect("u.id", "u.username", "p.balance").
    From("users", "u").
    Join(builder.InnerJoin, "profiles p", builder.Eq("p.user_id", builder.Raw("u.id"))).
    Where(
        builder.And(
            builder.Eq("u.is_active", true),
            builder.Gte("p.balance", 100.0),
        ),
    ).
    OrderBy("u.id", builder.OrderDesc).
    Limit(20).
    Offset(40).
    BuildWithDialect(builder.DialectPostgres)

// INSERT with Upsert (ON CONFLICT DO UPDATE)
sql, args = builder.NewInsert("users").
    Columns("id", "username", "email").
    Values(1, "alice", "alice@example.com").
    OnConflictDoUpdate(
        []string{"id"},
        builder.Assign("username", "alice"),
        builder.Assign("updated_at", builder.Raw("NOW()")),
    ).
    Returning("id").
    BuildWithDialect(builder.DialectPostgres)

Zero-Allocation ORM

Type-safe CRUD operations and model queries powered by precompiled memory offsets:

import "github.com/lemon4ksan/dawn/orm"

type Account struct {
    ID      int64   `db:"id,pk"`
    OwnerID int64   `db:"owner_id"`
    Status  string  `db:"status"`
    Balance float64 `db:"balance"`
}

// 1. Generic Repository
repo := orm.NewRepository[Account](client, "accounts")

account := &Account{ID: 101, OwnerID: 42, Status: "active", Balance: 500.0}
err := repo.Create(ctx, account)
err = repo.Update(ctx, account)

// 2. Fluent Model Queries
activeAccounts, err := orm.Model[Account](client).
    WhereEq("status", "active").
    WhereGt("balance", 100.0).
    OrderBy("balance", "DESC").
    Limit(25).
    Find(ctx)

Hardware-Sympathetic Types

import "github.com/lemon4ksan/dawn/types"

// 1. CompactString: 16-byte German/Umbra short string (<= 12 bytes inlined in registers)
cs := types.NewCompactString("short_name") // 0 allocs, 0.47 ns comparison

// 2. ValidityMask: 64-bit word bitmap with hardware POPCNT for 8x NULL memory reduction
mask := types.NewValidityMask(1024)
mask.SetNull(5)
isNull := mask.IsNull(5)

// 3. Point: OGC / PostGIS Well-Known Binary (WKB) 2D coordinates
pt := types.Point{X: 37.6173, Y: 55.7558} // 0.28 ns WKB conversion

// 4. ColumnVector: Contiguous memory columnar array for analytical workloads
col := types.NewColumnVector[int64](1024)
col.Append(100)
col.AppendNull()

Codegen Engine (sqlc Compatible)

dawn/codegen parses standard SQL annotations and generates typed models and query executors:

-- name: GetUserByID :one
SELECT id, username, email, location, is_active FROM users WHERE id = $1;

-- name: ListActiveUsers :many
SELECT id, username, email, location, is_active FROM users WHERE is_active = true;

-- name: DeleteUser :exec
DELETE FROM users WHERE id = $1;

Generates zero-allocation Go methods:

func (q *Queries) GetUserByID(ctx context.Context, id int64) (User, error) {
    return dawn.QueryOne[User](ctx, q.db, GetUserByIDSQL, id)
}

Benchmarks

Benchmarked on AMD Ryzen / Intel Core CPU architectures under Go 1.27:

BenchmarkFlatTable_GetOID-32             3000000000          0.39 ns/op        0 B/op        0 allocs/op
BenchmarkCompactString_CompareInlined-32 2500000000          0.47 ns/op        0 B/op        0 allocs/op
BenchmarkPoint_ToWKB-32                  3500000000          0.28 ns/op        0 B/op        0 allocs/op
BenchmarkVarint_GetSQLiteVarint-32       1400000000          0.84 ns/op        0 B/op        0 allocs/op
BenchmarkFastLock_Uncontended-32          700000000          1.71 ns/op        0 B/op        0 allocs/op
BenchmarkSlottedPage_Find-32               90000000         12.87 ns/op        0 B/op        0 allocs/op
BenchmarkBTree_Get-32                      80000000         14.73 ns/op        0 B/op        0 allocs/op
BenchmarkBackpatchWriter_Write-32          60000000         19.98 ns/op        0 B/op        0 allocs/op
BenchmarkBuilder_Core-32                   24000000         49.52 ns/op        0 B/op        0 allocs/op
BenchmarkRepository_Create-32              12000000        100.80 ns/op        0 B/op        0 allocs/op

License

BSD-3-Clause. See LICENSE file.

About

🌅 The zero-allocation data access substrate and protocol driver engine for Go

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages