Skip to main content

Common Patterns

Soft Deletes

Add a nullable deleted_at column and filter by default:

message User {
option (ratel.table) = {
generate: true
table_name: "users"
indexes: [
{ columns: ["email"], unique: true, where: "deleted_at IS NULL" }
]
};

google.protobuf.Timestamp deleted_at = 5;
}

Query only active records:

users, _ := Users.Query(ctx, db,
Users.SelectAll().
Where(Users.DeletedAt.IsNull()),
)

Soft delete:

Users.QueryRow(ctx, db,
Users.Update().
Set(Users.DeletedAt.Set(time.Now())).
Where(Users.ID.Eq(1)).
Returning(Users.ID),
)

Composite Primary Keys

message OrderItem {
option (ratel.table) = {
generate: true
table_name: "order_items"
primary_key: { columns: ["order_id", "line_no"] }
};

int64 order_id = 1;
int32 line_no = 2;
}

Cross-Schema Foreign Keys

Reference tables in different schemas:

int64 user_id = 2 [(ratel.column) = {
constraints: {
references_schema: "auth"
references_table: "users"
references_column: "id"
on_delete: CASCADE
}
}];

Row-Level Security (RLS)

option (ratel.table) = {
generate: true
table_name: "documents"
post_statements: [
"ALTER TABLE {table} ENABLE ROW LEVEL SECURITY",
"CREATE POLICY tenant_isolation ON {table} USING (tenant_id = current_setting('app.tenant_id')::bigint)"
]
};

Partial Indexes

indexes: [
{
columns: ["email"]
unique: true
where: "is_deleted = false"
}
]

GIN Indexes for JSONB

option (ratel.table) = {
generate: true
indexes: [
{ columns: ["metadata"], using: "gin" }
]
};

Query with JSON operators:

Users.SelectAll().
Where(Users.Metadata.JSONContains(`{"role":"admin"}`))

Expression Indexes

indexes: [
{ expressions: ["lower(email)"], unique: true }
]

Covering Indexes

indexes: [
{
columns: ["user_id"]
include: ["created_at", "status"]
}
]

FOR UPDATE Locking

tx, _ := pool.Begin(ctx)

user, _ := Users.QueryRow(ctx, tx,
Users.SelectAll().
Where(Users.ID.Eq(1)).
ForUpdate(),
)
// user row is locked until transaction ends

Users.QueryRow(ctx, tx,
Users.Update().
Set(Users.Balance.Set(user.Balance - amount)).
Where(Users.ID.Eq(1)).
Returning(Users.ID),
)

tx.Commit(ctx)