Compare commits
3 commits
79f47cf6ab
...
2f93383aa5
Author | SHA1 | Date | |
---|---|---|---|
2f93383aa5 | |||
650d2515be | |||
e2bce7e7a1 |
7 changed files with 47 additions and 17 deletions
|
@ -28,7 +28,7 @@ _ZRM_ provides a simple interface to relational databases in Zig. Define your re
|
||||||
|
|
||||||
## Versions
|
## Versions
|
||||||
|
|
||||||
ZRM 0.1.1 is made and tested with zig 0.13.0.
|
ZRM 0.1.2 is made and tested with zig 0.13.0.
|
||||||
|
|
||||||
## Work in progress
|
## 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:
|
In your project directory:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ zig fetch --save https://code.zeptotech.net/zedd/zrm/archive/v0.1.1.tar.gz
|
$ zig fetch --save https://code.zeptotech.net/zedd/zrm/archive/v0.1.2.tar.gz
|
||||||
```
|
```
|
||||||
|
|
||||||
In `build.zig`:
|
In `build.zig`:
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
.{
|
.{
|
||||||
.name = "zrm",
|
.name = "zrm",
|
||||||
.version = "0.1.1",
|
.version = "0.1.2",
|
||||||
|
|
||||||
.minimum_zig_version = "0.13.0",
|
.minimum_zig_version = "0.13.0",
|
||||||
|
|
||||||
|
|
29
src/helpers.zig
Normal file
29
src/helpers.zig
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
/// Simple ModelFromSql and ModelToSql functions for models which have the same table definition.
|
||||||
|
pub fn TableModel(comptime Model: type, comptime TableShape: type) type {
|
||||||
|
// Get fields of the model, which must be the same as the table shape.
|
||||||
|
const fields = std.meta.fields(Model);
|
||||||
|
|
||||||
|
return struct {
|
||||||
|
/// Simply copy all fields from model to table.
|
||||||
|
pub fn copyModelToTable(_model: Model) !TableShape {
|
||||||
|
var _table: TableShape = undefined;
|
||||||
|
inline for (fields) |modelField| {
|
||||||
|
// Copy each field of the model to the table.
|
||||||
|
@field(_table, modelField.name) = @field(_model, modelField.name);
|
||||||
|
}
|
||||||
|
return _table;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Simply copy all fields from table to model.
|
||||||
|
pub fn copyTableToModel(_table: TableShape) !Model {
|
||||||
|
var _model: Model = undefined;
|
||||||
|
inline for (fields) |tableField| {
|
||||||
|
// Copy each field of the table to the model.
|
||||||
|
@field(_model, tableField.name) = @field(_table, tableField.name);
|
||||||
|
}
|
||||||
|
return _model;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -7,7 +7,7 @@ const _sql = @import("sql.zig");
|
||||||
const repository = @import("repository.zig");
|
const repository = @import("repository.zig");
|
||||||
|
|
||||||
/// Type of an insertable column. Insert shape should be composed of only these.
|
/// Type of an insertable column. Insert shape should be composed of only these.
|
||||||
pub fn Insertable(comptime ValueType: type) type {
|
fn InsertableColumn(comptime ValueType: type) type {
|
||||||
return struct {
|
return struct {
|
||||||
value: ?ValueType = null,
|
value: ?ValueType = null,
|
||||||
default: bool = false,
|
default: bool = false,
|
||||||
|
@ -15,7 +15,7 @@ pub fn Insertable(comptime ValueType: type) type {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Build an insertable structure type from a normal structure.
|
/// Build an insertable structure type from a normal structure.
|
||||||
pub fn InsertableStruct(comptime StructType: type) type {
|
pub fn Insertable(comptime StructType: type) type {
|
||||||
// Get type info of the given structure.
|
// Get type info of the given structure.
|
||||||
const typeInfo = @typeInfo(StructType);
|
const typeInfo = @typeInfo(StructType);
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ pub fn InsertableStruct(comptime StructType: type) type {
|
||||||
var newFields: [typeInfo.Struct.fields.len]std.builtin.Type.StructField = undefined;
|
var newFields: [typeInfo.Struct.fields.len]std.builtin.Type.StructField = undefined;
|
||||||
for (typeInfo.Struct.fields, &newFields) |field, *newField| {
|
for (typeInfo.Struct.fields, &newFields) |field, *newField| {
|
||||||
// Create a new field for each field of the given struct.
|
// Create a new field for each field of the given struct.
|
||||||
const newFieldType = Insertable(field.type);
|
const newFieldType = InsertableColumn(field.type);
|
||||||
newField.* = std.builtin.Type.StructField{
|
newField.* = std.builtin.Type.StructField{
|
||||||
.name = field.name,
|
.name = field.name,
|
||||||
.type = newFieldType,
|
.type = newFieldType,
|
||||||
|
@ -47,7 +47,7 @@ pub fn InsertableStruct(comptime StructType: type) type {
|
||||||
/// Repository insert query configuration structure.
|
/// Repository insert query configuration structure.
|
||||||
pub fn RepositoryInsertConfiguration(comptime InsertShape: type) type {
|
pub fn RepositoryInsertConfiguration(comptime InsertShape: type) type {
|
||||||
return struct {
|
return struct {
|
||||||
values: []const InsertShape = undefined,
|
values: []const Insertable(InsertShape) = undefined,
|
||||||
returning: ?_sql.SqlParams = null,
|
returning: ?_sql.SqlParams = null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -124,7 +124,7 @@ pub fn RepositoryInsert(comptime Model: type, comptime TableShape: type, comptim
|
||||||
sql: ?[]const u8 = null,
|
sql: ?[]const u8 = null,
|
||||||
|
|
||||||
/// Parse given model or shape and put the result in newValue.
|
/// Parse given model or shape and put the result in newValue.
|
||||||
fn parseData(newValue: *InsertShape, value: anytype) !void {
|
fn parseData(newValue: *Insertable(InsertShape), value: anytype) !void {
|
||||||
// If the given value is a model, first convert it to its SQL equivalent.
|
// If the given value is a model, first convert it to its SQL equivalent.
|
||||||
if (@TypeOf(value) == Model) {
|
if (@TypeOf(value) == Model) {
|
||||||
return parseData(newValue, try repositoryConfig.toSql(value));
|
return parseData(newValue, try repositoryConfig.toSql(value));
|
||||||
|
@ -137,7 +137,7 @@ pub fn RepositoryInsert(comptime Model: type, comptime TableShape: type, comptim
|
||||||
|
|
||||||
/// Parse one value to insert.
|
/// Parse one value to insert.
|
||||||
fn parseOne(self: *Self, value: anytype) !void {
|
fn parseOne(self: *Self, value: anytype) !void {
|
||||||
const newValues = try self.arena.allocator().alloc(InsertShape, 1);
|
const newValues = try self.arena.allocator().alloc(Insertable(InsertShape), 1);
|
||||||
// Parse the given value.
|
// Parse the given value.
|
||||||
try parseData(&newValues[0], value);
|
try parseData(&newValues[0], value);
|
||||||
self.insertConfig.values = newValues;
|
self.insertConfig.values = newValues;
|
||||||
|
@ -145,7 +145,7 @@ pub fn RepositoryInsert(comptime Model: type, comptime TableShape: type, comptim
|
||||||
|
|
||||||
/// Parse a slice of values to insert.
|
/// Parse a slice of values to insert.
|
||||||
fn parseSlice(self: *Self, value: anytype) !void {
|
fn parseSlice(self: *Self, value: anytype) !void {
|
||||||
const newValues = try self.arena.allocator().alloc(InsertShape, value.len);
|
const newValues = try self.arena.allocator().alloc(Insertable(InsertShape), value.len);
|
||||||
for (0..value.len) |i| {
|
for (0..value.len) |i| {
|
||||||
// Parse each value in the given slice.
|
// Parse each value in the given slice.
|
||||||
try parseData(&newValues[i], value[i]);
|
try parseData(&newValues[i], value[i]);
|
||||||
|
|
|
@ -10,7 +10,6 @@ pub const RepositoryConfiguration = repository.RepositoryConfiguration;
|
||||||
pub const RepositoryResult = repository.RepositoryResult;
|
pub const RepositoryResult = repository.RepositoryResult;
|
||||||
|
|
||||||
pub const Insertable = insert.Insertable;
|
pub const Insertable = insert.Insertable;
|
||||||
pub const InsertableStruct = insert.InsertableStruct;
|
|
||||||
|
|
||||||
pub const QueryParameter = _sql.QueryParameter;
|
pub const QueryParameter = _sql.QueryParameter;
|
||||||
pub const SqlParams = _sql.SqlParams;
|
pub const SqlParams = _sql.SqlParams;
|
||||||
|
@ -18,3 +17,5 @@ pub const SqlParams = _sql.SqlParams;
|
||||||
pub const conditions = @import("conditions.zig");
|
pub const conditions = @import("conditions.zig");
|
||||||
|
|
||||||
pub const errors = @import("errors.zig");
|
pub const errors = @import("errors.zig");
|
||||||
|
|
||||||
|
pub const helpers = @import("helpers.zig");
|
||||||
|
|
|
@ -59,15 +59,15 @@ const CompositeModelRepository = zrm.Repository(CompositeModel, CompositeModelTa
|
||||||
.table = "composite_models",
|
.table = "composite_models",
|
||||||
|
|
||||||
// Insert shape used by default for inserts in the repository.
|
// Insert shape used by default for inserts in the repository.
|
||||||
.insertShape = zrm.InsertableStruct(struct {
|
.insertShape = struct {
|
||||||
secondcol: []const u8,
|
secondcol: []const u8,
|
||||||
label: []const u8,
|
label: []const u8,
|
||||||
}),
|
},
|
||||||
|
|
||||||
.key = &[_][]const u8{"firstcol", "secondcol"},
|
.key = &[_][]const u8{"firstcol", "secondcol"},
|
||||||
|
|
||||||
.fromSql = &modelFromSql,
|
.fromSql = &zrm.helpers.TableModel(CompositeModel, CompositeModelTable).copyTableToModel,
|
||||||
.toSql = &modelToSql,
|
.toSql = &zrm.helpers.TableModel(CompositeModel, CompositeModelTable).copyModelToTable,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -68,8 +68,8 @@ const MyModelRepository = zrm.Repository(MyModel, MyModelTable, .{
|
||||||
|
|
||||||
// Insert shape used by default for inserts in the repository.
|
// Insert shape used by default for inserts in the repository.
|
||||||
.insertShape = struct {
|
.insertShape = struct {
|
||||||
name: zrm.Insertable([]const u8),
|
name: []const u8,
|
||||||
amount: zrm.Insertable(f64),
|
amount: f64,
|
||||||
},
|
},
|
||||||
|
|
||||||
.key = &[_][]const u8{"id"},
|
.key = &[_][]const u8{"id"},
|
||||||
|
|
Loading…
Reference in a new issue