AI Agent Integration Guide
This guide is designed for AI coding assistants and developers. It outlines the directory patterns, model definition conventions, code generation workflows, and query APIs of the Enterprise ORM.
Directory Pattern
Projects utilizing the Enterprise ORM must adhere to the following standard layout:
your-project/
├── db_models/ # 1. Human-defined database table definitions (schema definitions)
│ ├── account.go
│ ├── group.go
│ └── constants.go # Helper constants for table & column names
├── generate/ # 2. Code-generation entrypoint
│ └── generate.go # Program containing main() that executes model generation
├── models/ # 3. Auto-generated ORM packages (DO NOT edit manually)
│ ├── client.go # Database initialization, transactions, and SQL loggers
│ ├── account.go # Model struct, getters, setters, hooks, and list/bulk operations
│ └── account_predicates.go # Code-generated WHERE filters for the model
├── migrate/ # 4. Schema migrations runner
│ └── migrate.go # Program to compute diffs and run migrations
└── main.go # Application entrypoint
Defining Tables (Schemas)
Table schemas are defined as Go functions under the db_models package. Each function returns a *models.Table.
Schema Rules & Guidelines
Quoting & Keyword Safety: Enterprise automatically double-quotes all table and column names in SQL. Always specify identifiers exactly as they should appear in DB.
Primary Keys: Every table must have a primary key defined via
SetIDField().Builder Chaining: Field builders return instances supporting method chaining (
SetNillable(),AddSerial(),Default(),DefaultFunc()).
Supported Fields
Boolean:
models.BoolField(name)Byte:
models.ByteField(name)UUID:
models.UUIDField(name)Integers:
models.IntField(name),models.SmallIntField(name),models.BigIntField(name)Unsigned Integer:
models.UintField(name)Floats:
models.Float32Field(name),models.Float64Field(name)String:
models.StringField(name)Decimal:
models.DecimalField(name, precision, scale)String Array:
models.StringArrayField(name)Enum:
models.EnumField(name, stringSlice)Time:
models.TimeField(name)JSON:
models.JSONField(name)Custom Type:
models.CustomField(name, postgresType, valueScannerInstance)(requires implementingsql.Scanneranddriver.Valuer)
Declaring Relationships
Many-to-One:
models.ManyToOne(targetTable, targetPK, sourceFK)One-to-Many:
models.OneToMany(targetTable, sourcePK, targetFK)Many-to-Many:
models.ManyToMany(targetTable, sourceFK, targetFK, targetPK, joinTableName)
Example Schema: db_models/account.go
package db_models
import (
"github.com/MrSametBurgazoglu/enterprise/models"
"github.com/google/uuid"
)
func Account() *models.Table {
idField := models.UUIDField("ID").DefaultFunc(uuid.New)
tb := &models.Table{
Fields: []models.FieldI{
idField,
models.StringField("Name"),
models.StringField("Surname"),
models.UUIDField("DenemeID").SetNillable(),
models.UintField("Serial").AddSerial(),
},
Relations: []*models.Relation{
models.ManyToOne("Deneme", "id", "deneme_id"),
models.ManyToMany("Group", "account_id", "group_id", "id", "account_group"),
},
}
tb.SetTableName("account")
tb.SetIDField(idField)
tb.AddIndex("account_name_surname_idx", "Name", "Surname")
return tb
}
Code Generation Workflow
The generator script executes model generation. Create generate/generate.go:
package main
import (
"github.com/MrSametBurgazoglu/enterprise/generate"
"your-project/db_models"
)
func main() {
generate.Models(
db_models.Account(),
db_models.Group(),
)
}
Run the script from your terminal:
go run generate/generate.go
This automatically compiles the templates and writes out the complete models/ Go files.
Database Setup & Migrations
Initialize the database using models.Options and run auto-applied or file-based migrations.
package main
import (
"context"
"log"
"github.com/MrSametBurgazoglu/enterprise/migrate"
"your-project/db_models"
"your-project/models"
)
func main() {
ctx := context.Background()
postgresURL := "postgresql://user:pass@localhost:5432/db?sslmode=disable"
tables := []*models.Table{
db_models.Account(),
db_models.Group(),
}
migrate.AutoApplyMigration(ctx, postgresURL, "init_schema", tables...)
opts := &models.Options{
Url: postgresURL,
Debug: true,
}
db, err := models.NewDB(opts)
if err != nil {
log.Fatal(err)
}
defer db.Exit()
}
Eager Relation Loading & Eager Filtering
To load child relations and filter them dynamically in a single query (preventing N+1 query patterns), use the With[RelationName] methods.
account := models.NewAccount(ctx, db)
account.Where(account.IsIDEqual(accountID))
// Join and filter relations inline
account.WithDeneme(func(d *models.Deneme) {
d.Where(d.IsActiveEqual(true))
})
account.WithGroupList(func(gl *models.GroupList) {
gl.Where(gl.IsNameEqual("Admin Group"))
})
err = account.Get()
if err == nil {
if account.Deneme != nil {
log.Println("Active Deneme:", account.Deneme.GetID())
}
}
Query Predicates & Logical Composition
Where clauses accept a list of client.PredicateI interfaces.
Logical Composition: Nest queries using
models.And(...)andmodels.Or(...).Dynamic Filters: Use
WhereIf(cond, predicate)andWhereIn(cond, predicate)to append predicates only ifcond == true.Zero Predicates: Calling
Where()with no arguments behaves as a no-op (no SQL WHERE clause).Wildcards: Use case-sensitive
IsXLikeand case-insensitiveIsXILikepattern matching.
list := models.NewAccountList(ctx, db)
list.Where(
models.And(
models.Or(
list.IsNameEqual("Samet"),
list.IsNameILike("admin%"),
),
list.IsSerialGreater(10),
),
)
list.WhereIf(filterByStatus, list.IsStatusEqual("active"))
err = list.List()
Bulk and In-Database Operations
Avoid loading entities into memory for bulk inserts, updates, or deletes.
list := models.NewAccountList(ctx, db)
// Bulk Create
acc1 := models.NewAccount(ctx, db)
acc1.SetName("Alice")
acc2 := models.NewAccount(ctx, db)
acc2.SetName("Bob")
err := list.Create(acc1, acc2)
// In-Database Update (UpdateWhere)
list.Where(list.IsStatusEqual("pending"))
rowsUpdated, err := list.UpdateWhere(map[string]any{
"status": "active",
})
// In-Database Delete (DeleteWhere)
list.Where(list.IsStatusEqual("banned"))
rowsDeleted, err := list.DeleteWhere()
Aggregates and Iterators (Go 1.23)
Enterprise supports basic aggregates (Min, Max, Sum, Avg) on model fields as well as standard library iterators.
Model Convenience Methods
denemeList := models.NewDenemeList(ctx, db)
maxVal, err := denemeList.MaxCount()
Group By and Go 1.23 iter.Seq2 Iterators
groupList := models.NewGroupList(ctx, db)
var (
groupName string
groupSize int
)
iterator := groupList.AggregateRowsSeq(func(a *client.Aggregate) {
a.Field("name", &groupName)
a.Count("id", &groupSize)
a.GroupBy("name")
})
for index, err := range iterator {
if err != nil {
log.Fatal(err)
}
fmt.Printf("Group %d: Name: %s, Size: %d\n", index, groupName, groupSize)
}