Compare commits

...

6 commits
v0.3.0 ... main

Author SHA1 Message Date
8dede5fad6
Fix returningColumns.
All checks were successful
/ build_docs (push) Successful in 30s
2025-01-14 11:52:10 +01:00
db6b019b5d
Add auto docs build with repository actions. 2025-01-14 11:48:47 +01:00
20360fc412
Add docs artifact build script. 2025-01-13 00:07:42 +01:00
f93af6c717
Version 0.3.1 2025-01-13 00:02:55 +01:00
c6db34694a
Uniformize and fix ZrmErrors references. 2025-01-12 23:56:37 +01:00
1f6125d2e1
Add commitAll and rollbackAll in sessions and recommend rollbackAll in defer in docs. 2025-01-12 23:52:53 +01:00
12 changed files with 79 additions and 26 deletions

View file

@ -0,0 +1,24 @@
on:
push:
tags:
- "*"
jobs:
build_docs:
runs-on: docker
container:
image: docker.zeptotech.net/zeptotech/zig-yarn:1.1.0
credentials:
username: ${{ vars.DOCKER_REGISTRY_USERNAME }}
password: ${{ secrets.DOCKER_REGISTRY_PASSWORD }}
steps:
- uses: actions/checkout@v4
- run: mkdir -p artifact/api
- run: (cd docs && corepack enable && yarn install)
- run: (cd docs && yarn docs:build)
- run: mv docs/.vitepress/dist/* artifact
- run: /zig/zig build docs
- run: mv zig-out/docs/* artifact/api
- uses: https://code.forgejo.org/forgejo/upload-artifact@v4
with:
name: docs.zip
path: artifact

View file

@ -28,7 +28,7 @@ _ZRM_ provides a simple interface to relational databases in Zig. Define your re
## Versions
ZRM 0.3.0 is made and tested with zig 0.13.0.
ZRM 0.3.1 is made and tested with zig 0.13.0.
## Work in progress
@ -41,7 +41,7 @@ ZRM aims to handle a lot for you, but it takes time to make. Have a look to [the
In your project directory:
```shell
$ zig fetch --save https://code.zeptotech.net/zedd/zrm/archive/v0.3.0.tar.gz
$ zig fetch --save https://code.zeptotech.net/zedd/zrm/archive/v0.3.1.tar.gz
```
In `build.zig`:

View file

@ -1,6 +1,6 @@
.{
.name = "zrm",
.version = "0.3.0",
.version = "0.3.1",
.minimum_zig_version = "0.13.0",

View file

@ -51,7 +51,19 @@ defer session.deinit();
Using sessions, you can start transactions and use savepoints.
::: warning
You probably want to rollback all active transactions in `defer`, so that none remain active after leaving the active branch.
:::
```zig
// Start a new session.
var session = try zrm.Session.init(database);
defer {
// Rollback all active transactions that remain active.
session.rollbackAll();
session.deinit();
};
try session.beginTransaction();
// Do something.

View file

@ -3,7 +3,7 @@
You can easily install ZRM using the `zig fetch` command:
```shell
$ zig fetch --save https://code.zeptotech.net/zedd/zrm/archive/v0.3.0.tar.gz
$ zig fetch --save https://code.zeptotech.net/zedd/zrm/archive/v0.3.1.tar.gz
```
::: info
@ -18,8 +18,8 @@ This should add something like the following in `build.zig.zon` dependencies:
.dependencies = .{
// ...
.zrm = .{
.url = "https://code.zeptotech.net/zedd/zrm/archive/v0.3.0.tar.gz",
.hash = "12200fe147879d72381633e6f44d76db2c8a603cda1969b4e474c15c31052dbb24b7",
.url = "https://code.zeptotech.net/zedd/zrm/archive/v0.3.1.tar.gz",
.hash = "12200fe...",
},
// ...
},

View file

@ -1,6 +1,6 @@
const std = @import("std");
const _sql = @import("sql.zig");
const errors = @import("errors.zig");
const ZrmError = @import("errors.zig").ZrmError;
const Static = @This();
@ -78,7 +78,7 @@ pub fn in(comptime ValueType: type, allocator: std.mem.Allocator, _column: []con
fn conditionsCombiner(comptime keyword: []const u8, allocator: std.mem.Allocator, subconditions: []const _sql.RawQuery) !_sql.RawQuery {
if (subconditions.len == 0) {
// At least one condition is required.
return errors.ZrmError.AtLeastOneConditionRequired;
return ZrmError.AtLeastOneConditionRequired;
}
// Full keyword constant.

View file

@ -1,7 +1,7 @@
const std = @import("std");
const pg = @import("pg");
const zollections = @import("zollections");
const errors = @import("errors.zig");
const ZrmError = @import("errors.zig").ZrmError;
const database = @import("database.zig");
const postgresql = @import("postgresql.zig");
const _sql = @import("sql.zig");
@ -196,14 +196,14 @@ pub fn RepositoryInsert(comptime Model: type, comptime TableShape: type, comptim
}
/// Set selected columns for RETURNING clause.
pub fn returningColumns(self: *Self, _select: []const []const u8) void {
pub fn returningColumns(self: *Self, _select: []const []const u8) !void {
if (_select.len == 0) {
return errors.AtLeastOneSelectionRequired;
return ZrmError.AtLeastOneSelectionRequired;
}
self.returning(.{
// Join selected columns.
.sql = std.mem.join(self.arena.allocator(), ", ", _select),
.sql = try std.mem.join(self.arena.allocator(), ", ", _select),
.params = &[_]_sql.RawQueryParameter{}, // No parameters.
});
}
@ -220,7 +220,7 @@ pub fn RepositoryInsert(comptime Model: type, comptime TableShape: type, comptim
pub fn buildSql(self: *Self) !void {
if (self.insertConfig.values.len == 0) {
// At least one value is required to insert.
return errors.ZrmError.AtLeastOneValueRequired;
return ZrmError.AtLeastOneValueRequired;
}
// Compute VALUES parameters count.

View file

@ -2,7 +2,7 @@ const std = @import("std");
const pg = @import("pg");
const zollections = @import("zollections");
const global = @import("global.zig");
const errors = @import("errors.zig");
const ZrmError = @import("errors.zig").ZrmError;
const database = @import("database.zig");
const _sql = @import("sql.zig");
const _relationships = @import("relationships.zig");
@ -51,7 +51,7 @@ pub fn handleRawPostgresqlError(err: anyerror, connection: *pg.Conn) anyerror {
}
// Return that an error happened in query execution.
return errors.ZrmError.QueryFailed;
return ZrmError.QueryFailed;
} else {
// Not an SQL error, just return it.
return err;

View file

@ -1,7 +1,7 @@
const std = @import("std");
const pg = @import("pg");
const zollections = @import("zollections");
const errors = @import("errors.zig");
const ZrmError = @import("errors.zig").ZrmError;
const database = @import("database.zig");
const postgresql = @import("postgresql.zig");
const _sql = @import("sql.zig");
@ -105,7 +105,7 @@ pub fn RepositoryQuery(comptime Model: type, comptime TableShape: type, comptime
/// Set selected columns for SELECT clause.
pub fn selectColumns(self: *Self, _select: []const []const u8) !void {
if (_select.len == 0) {
return errors.AtLeastOneSelectionRequired;
return ZrmError.AtLeastOneSelectionRequired;
}
self.select(.{

View file

@ -12,6 +12,9 @@ pub const Session = struct {
/// The active connection for the session.
connection: *pg.Conn,
/// The count of active transactions for the session.
activeTransactions: usize = 0,
/// Execute a comptime-known SQL command for the current session.
fn exec(self: Self, comptime sql: []const u8) !void {
_ = self.connection.exec(sql, .{}) catch |err| {
@ -29,11 +32,25 @@ pub const Session = struct {
try self.exec("ROLLBACK;");
}
/// Rollback all active transactions.
pub fn rollbackAll(self: Self) !void {
for (0..self.activeTransactions) |_| {
self.rollbackTransaction();
}
}
/// Commit the current transaction.
pub fn commitTransaction(self: Self) !void {
try self.exec("COMMIT;");
}
/// Commit all active transactions.
pub fn commitAll(self: Self) !void {
for (0..self.activeTransactions) |_| {
self.commitTransaction();
}
}
/// Create a new savepoint with the given name.
pub fn savepoint(self: Self, comptime _savepoint: []const u8) !void {
try self.exec("SAVEPOINT " ++ _savepoint ++ ";");

View file

@ -1,5 +1,5 @@
const std = @import("std");
const errors = @import("errors.zig");
const ZrmError = @import("errors.zig").ZrmError;
/// A structure with SQL and its parameters.
pub const RawQuery = struct {
@ -120,7 +120,7 @@ pub const RawQueryParameter = union(enum) {
null: void,
/// Convert any value to a query parameter.
pub fn fromValue(value: anytype) errors.ZrmError!RawQueryParameter {
pub fn fromValue(value: anytype) ZrmError!RawQueryParameter {
// Get given value type.
const valueType = @typeInfo(@TypeOf(value));
@ -138,7 +138,7 @@ pub const RawQueryParameter = union(enum) {
if (pointer.child == u8) {
return .{ .string = value };
} else {
return errors.ZrmError.UnsupportedTableType;
return ZrmError.UnsupportedTableType;
}
}
},
@ -154,7 +154,7 @@ pub const RawQueryParameter = union(enum) {
return .{ .null = true };
}
},
else => return errors.ZrmError.UnsupportedTableType
else => return ZrmError.UnsupportedTableType
};
}
};

View file

@ -1,7 +1,7 @@
const std = @import("std");
const pg = @import("pg");
const zollections = @import("zollections");
const errors = @import("errors.zig");
const ZrmError = @import("errors.zig").ZrmError;
const database = @import("database.zig");
const postgresql = @import("postgresql.zig");
const _sql = @import("sql.zig");
@ -153,14 +153,14 @@ pub fn RepositoryUpdate(comptime Model: type, comptime TableShape: type, comptim
}
/// Set selected columns for RETURNING clause.
pub fn returningColumns(self: *Self, _select: []const []const u8) void {
pub fn returningColumns(self: *Self, _select: []const []const u8) !void {
if (_select.len == 0) {
return errors.AtLeastOneSelectionRequired;
return ZrmError.AtLeastOneSelectionRequired;
}
self.returning(.{
// Join selected columns.
.sql = std.mem.join(self.arena.allocator(), ", ", _select),
.sql = try std.mem.join(self.arena.allocator(), ", ", _select),
.params = &[_]_sql.RawQueryParameter{}, // No parameters.
});
}
@ -177,7 +177,7 @@ pub fn RepositoryUpdate(comptime Model: type, comptime TableShape: type, comptim
pub fn buildSql(self: *Self) !void {
if (self.updateConfig.value) |_| {} else {
// Updated values must be set.
return errors.ZrmError.UpdatedValuesRequired;
return ZrmError.UpdatedValuesRequired;
}
// Start parameter counter at 1.