parent
66cf93d6f7
commit
b897ce70ab
11 changed files with 205 additions and 205 deletions
|
@ -5,7 +5,7 @@ const global = @import("global.zig");
|
|||
const errors = @import("errors.zig");
|
||||
const database = @import("database.zig");
|
||||
const _sql = @import("sql.zig");
|
||||
const _relations = @import("relations.zig");
|
||||
const _relationships = @import("relationships.zig");
|
||||
const repository = @import("repository.zig");
|
||||
const _result = @import("result.zig");
|
||||
|
||||
|
@ -213,29 +213,29 @@ pub fn makeMapper(comptime T: type, result: *pg.Result, allocator: std.mem.Alloc
|
|||
}
|
||||
|
||||
/// PostgreSQL implementation of the query result reader.
|
||||
pub fn QueryResultReader(comptime TableShape: type, comptime MetadataShape: ?type, comptime inlineRelations: ?[]const _relations.Relation) type {
|
||||
const InstanceInterface = _result.QueryResultReader(TableShape, MetadataShape, inlineRelations).Instance;
|
||||
pub fn QueryResultReader(comptime TableShape: type, comptime MetadataShape: ?type, comptime inlineRelationships: ?[]const _relationships.Relationship) type {
|
||||
const InstanceInterface = _result.QueryResultReader(TableShape, MetadataShape, inlineRelationships).Instance;
|
||||
|
||||
// Build relations mappers container type.
|
||||
const RelationsMappersType = comptime typeBuilder: {
|
||||
if (inlineRelations) |_inlineRelations| {
|
||||
// Make a field for each relation.
|
||||
var fields: [_inlineRelations.len]std.builtin.Type.StructField = undefined;
|
||||
// Build relationships mappers container type.
|
||||
const RelationshipsMappersType = comptime typeBuilder: {
|
||||
if (inlineRelationships) |_inlineRelationships| {
|
||||
// Make a field for each relationship.
|
||||
var fields: [_inlineRelationships.len]std.builtin.Type.StructField = undefined;
|
||||
|
||||
for (_inlineRelations, &fields) |relation, *field| {
|
||||
// Get relation field type (TableShape of the related value).
|
||||
const relationFieldType = PgMapper(relation.TableShape);
|
||||
for (_inlineRelationships, &fields) |relationship, *field| {
|
||||
// Get relationship field type (TableShape of the related value).
|
||||
const relationshipFieldType = PgMapper(relationship.TableShape);
|
||||
|
||||
field.* = .{
|
||||
.name = relation.field ++ [0:0]u8{},
|
||||
.type = relationFieldType,
|
||||
.name = relationship.field ++ [0:0]u8{},
|
||||
.type = relationshipFieldType,
|
||||
.default_value = null,
|
||||
.is_comptime = false,
|
||||
.alignment = @alignOf(relationFieldType),
|
||||
.alignment = @alignOf(relationshipFieldType),
|
||||
};
|
||||
}
|
||||
|
||||
// Build type with one field for each relation.
|
||||
// Build type with one field for each relationship.
|
||||
break :typeBuilder @Type(std.builtin.Type{
|
||||
.Struct = .{
|
||||
.layout = std.builtin.Type.ContainerLayout.auto,
|
||||
|
@ -265,9 +265,9 @@ pub fn QueryResultReader(comptime TableShape: type, comptime MetadataShape: ?typ
|
|||
/// Main object mapper.
|
||||
mainMapper: PgMapper(TableShape) = undefined,
|
||||
metadataMapper: PgMapper(MetadataShape orelse struct {}) = undefined,
|
||||
relationsMappers: RelationsMappersType = undefined,
|
||||
relationshipsMappers: RelationshipsMappersType = undefined,
|
||||
|
||||
fn next(opaqueSelf: *anyopaque) !?_result.TableWithRelations(TableShape, MetadataShape, inlineRelations) {
|
||||
fn next(opaqueSelf: *anyopaque) !?_result.TableWithRelationships(TableShape, MetadataShape, inlineRelationships) {
|
||||
const self: *Instance = @ptrCast(@alignCast(opaqueSelf));
|
||||
|
||||
// Try to get the next row.
|
||||
|
@ -277,17 +277,17 @@ pub fn QueryResultReader(comptime TableShape: type, comptime MetadataShape: ?typ
|
|||
const mainTable = try self.mainMapper.next(&row) orelse return null;
|
||||
|
||||
// Initialize the result.
|
||||
var result: _result.TableWithRelations(TableShape, MetadataShape, inlineRelations) = undefined;
|
||||
var result: _result.TableWithRelationships(TableShape, MetadataShape, inlineRelationships) = undefined;
|
||||
|
||||
// Copy each basic table field.
|
||||
inline for (std.meta.fields(TableShape)) |field| {
|
||||
@field(result, field.name) = @field(mainTable, field.name);
|
||||
}
|
||||
|
||||
if (inlineRelations) |_inlineRelations| {
|
||||
// For each relation, retrieve its value and put it in the result.
|
||||
inline for (_inlineRelations) |relation| {
|
||||
@field(result, relation.field) = @field(self.relationsMappers, relation.field).next(&row) catch null;
|
||||
if (inlineRelationships) |_inlineRelationships| {
|
||||
// For each relationship, retrieve its value and put it in the result.
|
||||
inline for (_inlineRelationships) |relationship| {
|
||||
@field(result, relationship.field) = @field(self.relationshipsMappers, relationship.field).next(&row) catch null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -323,11 +323,11 @@ pub fn QueryResultReader(comptime TableShape: type, comptime MetadataShape: ?typ
|
|||
self.instance.metadataMapper = try makeMapper(MetadataType, self.result, allocator, null);
|
||||
}
|
||||
|
||||
if (inlineRelations) |_inlineRelations| {
|
||||
// Initialize mapper for each relation.
|
||||
inline for (_inlineRelations) |relation| {
|
||||
@field(self.instance.relationsMappers, relation.field) =
|
||||
try makeMapper(relation.TableShape, self.result, allocator, "relations." ++ relation.field ++ ".");
|
||||
if (inlineRelationships) |_inlineRelationships| {
|
||||
// Initialize mapper for each relationship.
|
||||
inline for (_inlineRelationships) |relationship| {
|
||||
@field(self.instance.relationshipsMappers, relationship.field) =
|
||||
try makeMapper(relationship.TableShape, self.result, allocator, "relationships." ++ relationship.field ++ ".");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -335,7 +335,7 @@ pub fn QueryResultReader(comptime TableShape: type, comptime MetadataShape: ?typ
|
|||
}
|
||||
|
||||
/// Get the generic reader instance.
|
||||
pub fn reader(self: *Self) _result.QueryResultReader(TableShape, MetadataShape, inlineRelations) {
|
||||
pub fn reader(self: *Self) _result.QueryResultReader(TableShape, MetadataShape, inlineRelationships) {
|
||||
return .{
|
||||
._interface = .{
|
||||
.instance = self,
|
||||
|
|
|
@ -6,7 +6,7 @@ const database = @import("database.zig");
|
|||
const postgresql = @import("postgresql.zig");
|
||||
const _sql = @import("sql.zig");
|
||||
const _conditions = @import("conditions.zig");
|
||||
const relations = @import("relations.zig");
|
||||
const _relationships = @import("relationships.zig");
|
||||
const repository = @import("repository.zig");
|
||||
const _comptime = @import("comptime.zig");
|
||||
const _result = @import("result.zig");
|
||||
|
@ -18,57 +18,57 @@ pub const RepositoryQueryConfiguration = struct {
|
|||
where: ?_sql.RawQuery = null,
|
||||
};
|
||||
|
||||
/// Compiled relations structure.
|
||||
const CompiledRelations = struct {
|
||||
inlineRelations: []relations.Relation,
|
||||
otherRelations: []relations.Relation,
|
||||
/// Compiled relationships structure.
|
||||
const CompiledRelationships = struct {
|
||||
inlineRelationships: []_relationships.Relationship,
|
||||
otherRelationships: []_relationships.Relationship,
|
||||
inlineSelect: []const u8,
|
||||
inlineJoins: []const u8,
|
||||
};
|
||||
|
||||
/// Repository models query manager.
|
||||
/// Manage query string build and its execution.
|
||||
pub fn RepositoryQuery(comptime Model: type, comptime TableShape: type, comptime repositoryConfig: repository.RepositoryConfiguration(Model, TableShape), comptime with: ?[]const relations.Relation, comptime MetadataShape: ?type) type {
|
||||
const compiledRelations = comptime compile: {
|
||||
// Inline relations list.
|
||||
var inlineRelations: []relations.Relation = &[0]relations.Relation{};
|
||||
// Other relations list.
|
||||
var otherRelations: []relations.Relation = &[0]relations.Relation{};
|
||||
pub fn RepositoryQuery(comptime Model: type, comptime TableShape: type, comptime repositoryConfig: repository.RepositoryConfiguration(Model, TableShape), comptime with: ?[]const _relationships.Relationship, comptime MetadataShape: ?type) type {
|
||||
const compiledRelationships = comptime compile: {
|
||||
// Inline relationships list.
|
||||
var inlineRelationships: []_relationships.Relationship = &[0]_relationships.Relationship{};
|
||||
// Other relationships list.
|
||||
var otherRelationships: []_relationships.Relationship = &[0]_relationships.Relationship{};
|
||||
|
||||
if (with) |_with| {
|
||||
// If there are relations to eager load, prepare their query.
|
||||
// If there are relationships to eager load, prepare their query.
|
||||
|
||||
// Initialize inline select array.
|
||||
var inlineSelect: [][]const u8 = &[0][]const u8{};
|
||||
// Initialize inline joins array.
|
||||
var inlineJoins: [][]const u8 = &[0][]const u8{};
|
||||
|
||||
for (_with) |relation| {
|
||||
// For each relation, determine if it's inline or not.
|
||||
if (relation.inlineMapping) {
|
||||
// Add the current relation to inline relations.
|
||||
inlineRelations = @ptrCast(@constCast(_comptime.append(inlineRelations, relation)));
|
||||
for (_with) |relationship| {
|
||||
// For each relationship, determine if it's inline or not.
|
||||
if (relationship.inlineMapping) {
|
||||
// Add the current relationship to inline relationships.
|
||||
inlineRelationships = @ptrCast(@constCast(_comptime.append(inlineRelationships, relationship)));
|
||||
|
||||
// Generate selected columns for the relation.
|
||||
inlineSelect = @ptrCast(@constCast(_comptime.append(inlineSelect, relation.select)));
|
||||
// Generate joined table for the relation.
|
||||
inlineJoins = @ptrCast(@constCast(_comptime.append(inlineJoins, relation.join)));
|
||||
// Generate selected columns for the relationship.
|
||||
inlineSelect = @ptrCast(@constCast(_comptime.append(inlineSelect, relationship.select)));
|
||||
// Generate joined table for the relationship.
|
||||
inlineJoins = @ptrCast(@constCast(_comptime.append(inlineJoins, relationship.join)));
|
||||
} else {
|
||||
// Add the current relation to other relations.
|
||||
otherRelations = @ptrCast(@constCast(_comptime.append(otherRelations, relation)));
|
||||
// Add the current relationship to other relationships.
|
||||
otherRelationships = @ptrCast(@constCast(_comptime.append(otherRelationships, relationship)));
|
||||
}
|
||||
}
|
||||
|
||||
break :compile CompiledRelations{
|
||||
.inlineRelations = inlineRelations,
|
||||
.otherRelations = otherRelations,
|
||||
break :compile CompiledRelationships{
|
||||
.inlineRelationships = inlineRelationships,
|
||||
.otherRelationships = otherRelationships,
|
||||
.inlineSelect = if (inlineSelect.len > 0) ", " ++ _comptime.join(", ", inlineSelect) else "",
|
||||
.inlineJoins = if (inlineJoins.len > 0) " " ++ _comptime.join(" ", inlineJoins) else "",
|
||||
};
|
||||
} else {
|
||||
break :compile CompiledRelations{
|
||||
.inlineRelations = &[0]relations.Relation{},
|
||||
.otherRelations = &[0]relations.Relation{},
|
||||
break :compile CompiledRelationships{
|
||||
.inlineRelationships = &[0]_relationships.Relationship{},
|
||||
.otherRelationships = &[0]_relationships.Relationship{},
|
||||
.inlineSelect = "",
|
||||
.inlineJoins = "",
|
||||
};
|
||||
|
@ -77,8 +77,8 @@ pub fn RepositoryQuery(comptime Model: type, comptime TableShape: type, comptime
|
|||
|
||||
// Pre-compute SQL buffer.
|
||||
const fromClause = " FROM \"" ++ repositoryConfig.table ++ "\"";
|
||||
const defaultSelectSql = "\"" ++ repositoryConfig.table ++ "\".*" ++ compiledRelations.inlineSelect;
|
||||
const defaultJoin = compiledRelations.inlineJoins;
|
||||
const defaultSelectSql = "\"" ++ repositoryConfig.table ++ "\".*" ++ compiledRelationships.inlineSelect;
|
||||
const defaultJoin = compiledRelationships.inlineJoins;
|
||||
|
||||
// Model key type.
|
||||
const KeyType = repository.ModelKeyType(Model, TableShape, repositoryConfig);
|
||||
|
@ -87,7 +87,7 @@ pub fn RepositoryQuery(comptime Model: type, comptime TableShape: type, comptime
|
|||
const Self = @This();
|
||||
|
||||
/// Result mapper type.
|
||||
pub const ResultMapper = _result.ResultMapper(Model, TableShape, MetadataShape, repositoryConfig, compiledRelations.inlineRelations, compiledRelations.otherRelations);
|
||||
pub const ResultMapper = _result.ResultMapper(Model, TableShape, MetadataShape, repositoryConfig, compiledRelationships.inlineRelationships, compiledRelationships.otherRelationships);
|
||||
|
||||
arena: std.heap.ArenaAllocator,
|
||||
connector: database.Connector,
|
||||
|
@ -296,7 +296,7 @@ pub fn RepositoryQuery(comptime Model: type, comptime TableShape: type, comptime
|
|||
defer queryResult.deinit();
|
||||
|
||||
// Map query results.
|
||||
var postgresqlReader = postgresql.QueryResultReader(TableShape, MetadataShape, compiledRelations.inlineRelations).init(queryResult);
|
||||
var postgresqlReader = postgresql.QueryResultReader(TableShape, MetadataShape, compiledRelationships.inlineRelationships).init(queryResult);
|
||||
return try ResultMapper.map(withMetadata, allocator, self.connector, postgresqlReader.reader());
|
||||
}
|
||||
|
||||
|
|
|
@ -5,9 +5,9 @@ const _sql = @import("sql.zig");
|
|||
const repository = @import("repository.zig");
|
||||
const _query = @import("query.zig");
|
||||
|
||||
/// Configure a "one to many" or "many to many" relation.
|
||||
/// Configure a "one to many" or "many to many" relationship.
|
||||
pub const ManyConfiguration = union(enum) {
|
||||
/// Direct one-to-many relation using a distant foreign key.
|
||||
/// Direct one-to-many relationship using a distant foreign key.
|
||||
direct: struct {
|
||||
/// The distant foreign key name pointing to the current model.
|
||||
foreignKey: []const u8,
|
||||
|
@ -16,7 +16,7 @@ pub const ManyConfiguration = union(enum) {
|
|||
modelKey: ?[]const u8 = null,
|
||||
},
|
||||
|
||||
/// Used when performing a many-to-many relation through an association table.
|
||||
/// Used when performing a many-to-many relationship through an association table.
|
||||
through: struct {
|
||||
/// Name of the join table.
|
||||
table: []const u8,
|
||||
|
@ -33,7 +33,7 @@ pub const ManyConfiguration = union(enum) {
|
|||
},
|
||||
};
|
||||
|
||||
/// Make a "one to many" or "many to many" relation.
|
||||
/// Make a "one to many" or "many to many" relationship.
|
||||
pub fn many(comptime fromRepo: anytype, comptime toRepo: anytype, comptime config: ManyConfiguration) type {
|
||||
return typedMany(
|
||||
fromRepo.ModelType, fromRepo.TableType, fromRepo.config,
|
||||
|
@ -42,7 +42,7 @@ pub fn many(comptime fromRepo: anytype, comptime toRepo: anytype, comptime confi
|
|||
);
|
||||
}
|
||||
|
||||
/// Internal implementation of a new "one to many" or "many to many" relation.
|
||||
/// Internal implementation of a new "one to many" or "many to many" relationship.
|
||||
pub fn typedMany(
|
||||
comptime FromModel: type, comptime FromTable: type,
|
||||
comptime fromRepositoryConfig: repository.RepositoryConfiguration(FromModel, FromTable),
|
||||
|
@ -51,15 +51,15 @@ pub fn typedMany(
|
|||
comptime config: ManyConfiguration) type {
|
||||
|
||||
return struct {
|
||||
/// Relation implementation.
|
||||
/// Relationship implementation.
|
||||
pub fn Implementation(field: []const u8) type {
|
||||
// Get foreign key from relation config or repository config.
|
||||
// Get foreign key from relationship config or repository config.
|
||||
const foreignKey = switch (config) {
|
||||
.direct => |direct| direct.foreignKey,
|
||||
.through => |through| if (through.foreignKey) |_foreignKey| _foreignKey else toRepositoryConfig.key[0],
|
||||
};
|
||||
|
||||
// Get model key from relation config or repository config.
|
||||
// Get model key from relationship config or repository config.
|
||||
const modelKey = switch (config) {
|
||||
.direct => |direct| if (direct.modelKey) |_modelKey| _modelKey else fromRepositoryConfig.key[0],
|
||||
.through => |through| if (through.modelKey) |_modelKey| _modelKey else fromRepositoryConfig.key[0],
|
||||
|
@ -68,10 +68,10 @@ pub fn typedMany(
|
|||
|
||||
const FromKeyType = std.meta.fields(FromModel)[std.meta.fieldIndex(FromModel, fromRepositoryConfig.key[0]).?].type;
|
||||
const QueryType = _query.RepositoryQuery(ToModel, ToTable, toRepositoryConfig, null, struct {
|
||||
__zrm_relation_key: FromKeyType,
|
||||
__zrm_relationship_key: FromKeyType,
|
||||
});
|
||||
|
||||
const alias = "relations." ++ field;
|
||||
const alias = "relationships." ++ field;
|
||||
const prefix = alias ++ ".";
|
||||
|
||||
return struct {
|
||||
|
@ -103,7 +103,7 @@ pub fn typedMany(
|
|||
.direct => {
|
||||
// Add SELECT.
|
||||
query.select(.{
|
||||
.sql = baseSelect ++ ", \"" ++ toRepositoryConfig.table ++ "\".\"" ++ foreignKey ++ "\" AS \"__zrm_relation_key\"",
|
||||
.sql = baseSelect ++ ", \"" ++ toRepositoryConfig.table ++ "\".\"" ++ foreignKey ++ "\" AS \"__zrm_relationship_key\"",
|
||||
.params = &[0]_sql.RawQueryParameter{},
|
||||
});
|
||||
|
||||
|
@ -113,7 +113,7 @@ pub fn typedMany(
|
|||
.through => |through| {
|
||||
// Add SELECT.
|
||||
query.select(.{
|
||||
.sql = baseSelect ++ ", \"" ++ prefix ++ "pivot" ++ "\".\"" ++ through.joinModelKey ++ "\" AS \"__zrm_relation_key\"",
|
||||
.sql = baseSelect ++ ", \"" ++ prefix ++ "pivot" ++ "\".\"" ++ through.joinModelKey ++ "\" AS \"__zrm_relationship_key\"",
|
||||
.params = &[0]_sql.RawQueryParameter{},
|
||||
});
|
||||
|
||||
|
@ -131,8 +131,8 @@ pub fn typedMany(
|
|||
return query; // Return built query.
|
||||
}
|
||||
|
||||
/// Build the "many" generic relation.
|
||||
pub fn relation(_: Self) Relation {
|
||||
/// Build the "many" generic relationship.
|
||||
pub fn relationship(_: Self) Relationship {
|
||||
return .{
|
||||
._interface = .{
|
||||
.repositoryConfiguration = &toRepositoryConfig,
|
||||
|
@ -157,9 +157,9 @@ pub fn typedMany(
|
|||
}
|
||||
|
||||
|
||||
/// Configure a "one to one" relation.
|
||||
/// Configure a "one to one" relationship.
|
||||
pub const OneConfiguration = union(enum) {
|
||||
/// Direct one-to-one relation using a local foreign key.
|
||||
/// Direct one-to-one relationship using a local foreign key.
|
||||
direct: struct {
|
||||
/// The local foreign key name.
|
||||
foreignKey: []const u8,
|
||||
|
@ -168,7 +168,7 @@ pub const OneConfiguration = union(enum) {
|
|||
modelKey: ?[]const u8 = null,
|
||||
},
|
||||
|
||||
/// Reverse one-to-one relation using distant foreign key.
|
||||
/// Reverse one-to-one relationship using distant foreign key.
|
||||
reverse: struct {
|
||||
/// The distant foreign key name.
|
||||
/// Use the default key name of the related model.
|
||||
|
@ -178,7 +178,7 @@ pub const OneConfiguration = union(enum) {
|
|||
modelKey: ?[]const u8 = null,
|
||||
},
|
||||
|
||||
/// Used when performing a one-to-one relation through an association table.
|
||||
/// Used when performing a one-to-one relationship through an association table.
|
||||
through: struct {
|
||||
/// Name of the join table.
|
||||
table: []const u8,
|
||||
|
@ -195,7 +195,7 @@ pub const OneConfiguration = union(enum) {
|
|||
},
|
||||
};
|
||||
|
||||
/// Make a "one to one" relation.
|
||||
/// Make a "one to one" relationship.
|
||||
pub fn one(comptime fromRepo: anytype, comptime toRepo: anytype, comptime config: OneConfiguration) type {
|
||||
return typedOne(
|
||||
fromRepo.ModelType, fromRepo.TableType, fromRepo.config,
|
||||
|
@ -204,7 +204,7 @@ pub fn one(comptime fromRepo: anytype, comptime toRepo: anytype, comptime config
|
|||
);
|
||||
}
|
||||
|
||||
/// Internal implementation of a new "one to one" relation.
|
||||
/// Internal implementation of a new "one to one" relationship.
|
||||
fn typedOne(
|
||||
comptime FromModel: type, comptime FromTable: type,
|
||||
comptime fromRepositoryConfig: repository.RepositoryConfiguration(FromModel, FromTable),
|
||||
|
@ -216,24 +216,24 @@ fn typedOne(
|
|||
pub fn Implementation(field: []const u8) type {
|
||||
const FromKeyType = std.meta.fields(FromModel)[std.meta.fieldIndex(FromModel, fromRepositoryConfig.key[0]).?].type;
|
||||
const QueryType = _query.RepositoryQuery(ToModel, ToTable, toRepositoryConfig, null, struct {
|
||||
__zrm_relation_key: FromKeyType,
|
||||
__zrm_relationship_key: FromKeyType,
|
||||
});
|
||||
|
||||
// Get foreign key from relation config or repository config.
|
||||
// Get foreign key from relationship config or repository config.
|
||||
const foreignKey = switch (config) {
|
||||
.direct => |direct| direct.foreignKey,
|
||||
.reverse => |reverse| if (reverse.foreignKey) |_foreignKey| _foreignKey else toRepositoryConfig.key[0],
|
||||
.through => |through| if (through.foreignKey) |_foreignKey| _foreignKey else fromRepositoryConfig.key[0],
|
||||
};
|
||||
|
||||
// Get model key from relation config or repository config.
|
||||
// Get model key from relationship config or repository config.
|
||||
const modelKey = switch (config) {
|
||||
.direct => |direct| if (direct.modelKey) |_modelKey| _modelKey else toRepositoryConfig.key[0],
|
||||
.reverse => |reverse| if (reverse.modelKey) |_modelKey| _modelKey else fromRepositoryConfig.key[0],
|
||||
.through => |through| if (through.modelKey) |_modelKey| _modelKey else toRepositoryConfig.key[0],
|
||||
};
|
||||
|
||||
const alias = "relations." ++ field;
|
||||
const alias = "relationships." ++ field;
|
||||
const prefix = alias ++ ".";
|
||||
|
||||
return struct {
|
||||
|
@ -286,7 +286,7 @@ fn typedOne(
|
|||
.direct => {
|
||||
// Add SELECT.
|
||||
query.select(.{
|
||||
.sql = baseSelect ++ ", \"" ++ fromRepositoryConfig.table ++ "\".\"" ++ fromRepositoryConfig.key[0] ++ "\" AS \"__zrm_relation_key\"",
|
||||
.sql = baseSelect ++ ", \"" ++ fromRepositoryConfig.table ++ "\".\"" ++ fromRepositoryConfig.key[0] ++ "\" AS \"__zrm_relationship_key\"",
|
||||
.params = &[0]_sql.RawQueryParameter{},
|
||||
});
|
||||
|
||||
|
@ -302,7 +302,7 @@ fn typedOne(
|
|||
.reverse => {
|
||||
// Add SELECT.
|
||||
query.select(.{
|
||||
.sql = baseSelect ++ ", \"" ++ toRepositoryConfig.table ++ "\".\"" ++ foreignKey ++ "\" AS \"__zrm_relation_key\"",
|
||||
.sql = baseSelect ++ ", \"" ++ toRepositoryConfig.table ++ "\".\"" ++ foreignKey ++ "\" AS \"__zrm_relationship_key\"",
|
||||
.params = &[0]_sql.RawQueryParameter{},
|
||||
});
|
||||
|
||||
|
@ -312,7 +312,7 @@ fn typedOne(
|
|||
.through => |through| {
|
||||
// Add SELECT.
|
||||
query.select(.{
|
||||
.sql = baseSelect ++ ", \"" ++ prefix ++ "pivot" ++ "\".\"" ++ through.joinForeignKey ++ "\" AS \"__zrm_relation_key\"",
|
||||
.sql = baseSelect ++ ", \"" ++ prefix ++ "pivot" ++ "\".\"" ++ through.joinForeignKey ++ "\" AS \"__zrm_relationship_key\"",
|
||||
.params = &[0]_sql.RawQueryParameter{},
|
||||
});
|
||||
|
||||
|
@ -331,8 +331,8 @@ fn typedOne(
|
|||
return query;
|
||||
}
|
||||
|
||||
/// Build the "one" generic relation.
|
||||
pub fn relation(_: Self) Relation {
|
||||
/// Build the "one" generic relationship.
|
||||
pub fn relationship(_: Self) Relationship {
|
||||
return .{
|
||||
._interface = .{
|
||||
.repositoryConfiguration = &toRepositoryConfig,
|
||||
|
@ -356,8 +356,8 @@ fn typedOne(
|
|||
};
|
||||
}
|
||||
|
||||
/// Generic model relation interface.
|
||||
pub const Relation = struct {
|
||||
/// Generic model relationship interface.
|
||||
pub const Relationship = struct {
|
||||
const Self = @This();
|
||||
|
||||
_interface: struct {
|
||||
|
@ -372,14 +372,14 @@ pub const Relation = struct {
|
|||
TableShape: type,
|
||||
/// Field where to put the related model(s).
|
||||
field: []const u8,
|
||||
/// Table alias of the relation.
|
||||
/// Table alias of the relationship.
|
||||
alias: []const u8,
|
||||
/// Prefix of fields of the relation.
|
||||
/// Prefix of fields of the relationship.
|
||||
prefix: []const u8,
|
||||
/// Type of a query of the related models.
|
||||
QueryType: type,
|
||||
|
||||
/// Set if relation mapping is done inline: this means that it's done at the same time the model is mapped,
|
||||
/// Set if relationship mapping is done inline: this means that it's done at the same time the model is mapped,
|
||||
/// and that the associated data will be retrieved in the main query.
|
||||
inlineMapping: bool,
|
||||
/// In case of inline mapping, the JOIN clause to retrieve the associated data.
|
||||
|
@ -387,8 +387,8 @@ pub const Relation = struct {
|
|||
/// The SELECT clause to retrieve the associated data.
|
||||
select: []const u8,
|
||||
|
||||
/// Build the query to retrieve relation data.
|
||||
/// Is always used when inline mapping is not possible, but also when loading relations lazily.
|
||||
/// Build the query to retrieve relationship data.
|
||||
/// Is always used when inline mapping is not possible, but also when loading relationships lazily.
|
||||
pub fn buildQuery(self: Self, models: []const *anyopaque, allocator: std.mem.Allocator, connector: _database.Connector) !*anyopaque {
|
||||
return self._interface.buildQuery(models, allocator, connector);
|
||||
}
|
||||
|
@ -402,10 +402,10 @@ pub const Relation = struct {
|
|||
};
|
||||
|
||||
|
||||
/// Structure of an eager loaded relation.
|
||||
/// Structure of an eager loaded relationship.
|
||||
pub const Eager = struct {
|
||||
/// The relation to eager load.
|
||||
relation: Relation,
|
||||
/// Subrelations to eager load.
|
||||
/// The relationship to eager load.
|
||||
relationship: Relationship,
|
||||
/// Subrelationships to eager load.
|
||||
with: []const Eager,
|
||||
};
|
|
@ -3,7 +3,7 @@ const zollections = @import("zollections");
|
|||
const database = @import("database.zig");
|
||||
const _sql = @import("sql.zig");
|
||||
const _conditions = @import("conditions.zig");
|
||||
const _relations = @import("relations.zig");
|
||||
const _relationships = @import("relationships.zig");
|
||||
const query = @import("query.zig");
|
||||
const insert = @import("insert.zig");
|
||||
const update = @import("update.zig");
|
||||
|
@ -74,18 +74,18 @@ pub fn ModelKeyType(comptime Model: type, comptime TableShape: type, comptime co
|
|||
}
|
||||
}
|
||||
|
||||
/// Model relations definition type.
|
||||
pub fn RelationsDefinitionType(comptime rawDefinition: anytype) type {
|
||||
/// Model relationships definition type.
|
||||
pub fn RelationshipsDefinitionType(comptime rawDefinition: anytype) type {
|
||||
const rawDefinitionType = @typeInfo(@TypeOf(rawDefinition));
|
||||
|
||||
// Build relations fields and implementations fields.
|
||||
// Build relationships fields and implementations fields.
|
||||
var fields: [1 + rawDefinitionType.Struct.fields.len]std.builtin.Type.StructField = undefined;
|
||||
var implementationsFields: [rawDefinitionType.Struct.fields.len]std.builtin.Type.StructField = undefined;
|
||||
|
||||
inline for (rawDefinitionType.Struct.fields, fields[1..], &implementationsFields) |originalField, *field, *implementationField| {
|
||||
field.* = std.builtin.Type.StructField{
|
||||
.name = originalField.name,
|
||||
.type = _relations.Relation,
|
||||
.type = _relationships.Relationship,
|
||||
.default_value = null,
|
||||
.is_comptime = false,
|
||||
.alignment = @alignOf(type),
|
||||
|
@ -144,34 +144,34 @@ pub fn Repository(comptime Model: type, comptime TableShape: type, comptime repo
|
|||
/// Type of one model key.
|
||||
pub const KeyType = ModelKeyType(Model, TableShape, config);
|
||||
|
||||
pub const relations = struct {
|
||||
/// Make a "one to one" relation.
|
||||
pub fn one(comptime toRepo: anytype, comptime oneConfig: _relations.OneConfiguration) type {
|
||||
return _relations.one(Self, toRepo, oneConfig);
|
||||
pub const relationships = struct {
|
||||
/// Make a "one to one" relationship.
|
||||
pub fn one(comptime toRepo: anytype, comptime oneConfig: _relationships.OneConfiguration) type {
|
||||
return _relationships.one(Self, toRepo, oneConfig);
|
||||
}
|
||||
|
||||
/// Make a "one to many" or "many to many" relation.
|
||||
pub fn many(comptime toRepo: anytype, comptime manyConfig: _relations.ManyConfiguration) type {
|
||||
return _relations.many(Self, toRepo, manyConfig);
|
||||
/// Make a "one to many" or "many to many" relationship.
|
||||
pub fn many(comptime toRepo: anytype, comptime manyConfig: _relationships.ManyConfiguration) type {
|
||||
return _relationships.many(Self, toRepo, manyConfig);
|
||||
}
|
||||
|
||||
/// Define a relations object for a repository.
|
||||
pub fn define(rawDefinition: anytype) RelationsDefinitionType(rawDefinition) {
|
||||
/// Define a relationships object for a repository.
|
||||
pub fn define(rawDefinition: anytype) RelationshipsDefinitionType(rawDefinition) {
|
||||
const rawDefinitionType = @TypeOf(rawDefinition);
|
||||
|
||||
// Initialize final relations definition.
|
||||
var definition: RelationsDefinitionType(rawDefinition) = undefined;
|
||||
// Initialize final relationships definition.
|
||||
var definition: RelationshipsDefinitionType(rawDefinition) = undefined;
|
||||
|
||||
definition._implementations = .{};
|
||||
|
||||
// Check that the definition structure only include known fields.
|
||||
inline for (std.meta.fieldNames(rawDefinitionType)) |fieldName| {
|
||||
if (!@hasField(Model, fieldName)) {
|
||||
@compileError("No corresponding field for relation " ++ fieldName);
|
||||
@compileError("No corresponding field for relationship " ++ fieldName);
|
||||
}
|
||||
|
||||
// Alter definition structure to set the relation instance.
|
||||
@field(definition, fieldName) = @field(definition._implementations, fieldName).relation();
|
||||
// Alter definition structure to set the relationship instance.
|
||||
@field(definition, fieldName) = @field(definition._implementations, fieldName).relationship();
|
||||
}
|
||||
|
||||
// Return altered definition structure.
|
||||
|
@ -179,7 +179,7 @@ pub fn Repository(comptime Model: type, comptime TableShape: type, comptime repo
|
|||
}
|
||||
};
|
||||
|
||||
pub fn QueryWith(comptime with: []const _relations.Relation) type {
|
||||
pub fn QueryWith(comptime with: []const _relationships.Relationship) type {
|
||||
return query.RepositoryQuery(Model, TableShape, config, with, null);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ const std = @import("std");
|
|||
const zollections = @import("zollections");
|
||||
const _database = @import("database.zig");
|
||||
const _repository = @import("repository.zig");
|
||||
const _relations = @import("relations.zig");
|
||||
const _relationships = @import("relationships.zig");
|
||||
|
||||
/// Structure of a model with its metadata.
|
||||
pub fn ModelWithMetadata(comptime Model: type, comptime MetadataShape: ?type) type {
|
||||
|
@ -16,38 +16,38 @@ pub fn ModelWithMetadata(comptime Model: type, comptime MetadataShape: ?type) ty
|
|||
}
|
||||
}
|
||||
|
||||
/// Type of a retrieved table data, with its retrieved relations.
|
||||
pub fn TableWithRelations(comptime TableShape: type, comptime MetadataShape: ?type, comptime optionalRelations: ?[]const _relations.Relation) type {
|
||||
if (optionalRelations) |relations| {
|
||||
/// Type of a retrieved table data, with its retrieved relationships.
|
||||
pub fn TableWithRelationships(comptime TableShape: type, comptime MetadataShape: ?type, comptime optionalRelationships: ?[]const _relationships.Relationship) type {
|
||||
if (optionalRelationships) |relationships| {
|
||||
const tableType = @typeInfo(TableShape);
|
||||
|
||||
// Build fields list: copy the existing table type fields and add those for relations.
|
||||
var fields: [tableType.Struct.fields.len + relations.len + (if (MetadataShape) |_| 1 else 0)]std.builtin.Type.StructField = undefined;
|
||||
// Build fields list: copy the existing table type fields and add those for relationships.
|
||||
var fields: [tableType.Struct.fields.len + relationships.len + (if (MetadataShape) |_| 1 else 0)]std.builtin.Type.StructField = undefined;
|
||||
// Copy base table fields.
|
||||
@memcpy(fields[0..tableType.Struct.fields.len], tableType.Struct.fields);
|
||||
|
||||
// For each relation, create a new struct field in the table shape.
|
||||
for (relations, fields[tableType.Struct.fields.len..(tableType.Struct.fields.len+relations.len)]) |relation, *field| {
|
||||
// Get relation field type (optional TableShape of the related value).
|
||||
const relationFieldType = @Type(std.builtin.Type{
|
||||
// For each relationship, create a new struct field in the table shape.
|
||||
for (relationships, fields[tableType.Struct.fields.len..(tableType.Struct.fields.len+relationships.len)]) |relationship, *field| {
|
||||
// Get relationship field type (optional TableShape of the related value).
|
||||
const relationshipFieldType = @Type(std.builtin.Type{
|
||||
.Optional = .{
|
||||
.child = relation.TableShape
|
||||
.child = relationship.TableShape
|
||||
},
|
||||
});
|
||||
|
||||
// Create the new field from relation data.
|
||||
// Create the new field from relationship data.
|
||||
field.* = std.builtin.Type.StructField{
|
||||
.name = relation.field ++ [0:0]u8{},
|
||||
.type = relationFieldType,
|
||||
.name = relationship.field ++ [0:0]u8{},
|
||||
.type = relationshipFieldType,
|
||||
.default_value = null,
|
||||
.is_comptime = false,
|
||||
.alignment = @alignOf(relationFieldType),
|
||||
.alignment = @alignOf(relationshipFieldType),
|
||||
};
|
||||
}
|
||||
|
||||
if (MetadataShape) |MetadataType| {
|
||||
// Add metadata field.
|
||||
fields[tableType.Struct.fields.len + relations.len] = std.builtin.Type.StructField{
|
||||
fields[tableType.Struct.fields.len + relationships.len] = std.builtin.Type.StructField{
|
||||
.name = "_zrm_metadata",
|
||||
.type = MetadataType,
|
||||
.default_value = null,
|
||||
|
@ -72,8 +72,8 @@ pub fn TableWithRelations(comptime TableShape: type, comptime MetadataShape: ?ty
|
|||
}
|
||||
|
||||
/// Convert a value of the fully retrieved type to the TableShape type.
|
||||
pub fn toTableShape(comptime TableShape: type, comptime MetadataShape: ?type, comptime optionalRelations: ?[]const _relations.Relation, value: TableWithRelations(TableShape, MetadataShape, optionalRelations)) TableShape {
|
||||
if (optionalRelations) |_| {
|
||||
pub fn toTableShape(comptime TableShape: type, comptime MetadataShape: ?type, comptime optionalRelationships: ?[]const _relationships.Relationship, value: TableWithRelationships(TableShape, MetadataShape, optionalRelationships)) TableShape {
|
||||
if (optionalRelationships) |_| {
|
||||
// Make a structure of TableShape type.
|
||||
var tableValue: TableShape = undefined;
|
||||
|
||||
|
@ -85,13 +85,13 @@ pub fn toTableShape(comptime TableShape: type, comptime MetadataShape: ?type, co
|
|||
// Return the simplified structure.
|
||||
return tableValue;
|
||||
} else {
|
||||
// No relations, it should already be of type TableShape.
|
||||
// No relationships, it should already be of type TableShape.
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/// Generic interface of a query result reader.
|
||||
pub fn QueryResultReader(comptime TableShape: type, comptime MetadataShape: ?type, comptime inlineRelations: ?[]const _relations.Relation) type {
|
||||
pub fn QueryResultReader(comptime TableShape: type, comptime MetadataShape: ?type, comptime inlineRelationships: ?[]const _relationships.Relationship) type {
|
||||
return struct {
|
||||
const Self = @This();
|
||||
|
||||
|
@ -99,12 +99,12 @@ pub fn QueryResultReader(comptime TableShape: type, comptime MetadataShape: ?typ
|
|||
pub const Instance = struct {
|
||||
__interface: struct {
|
||||
instance: *anyopaque,
|
||||
next: *const fn (self: *anyopaque) anyerror!?TableWithRelations(TableShape, MetadataShape, inlineRelations),
|
||||
next: *const fn (self: *anyopaque) anyerror!?TableWithRelationships(TableShape, MetadataShape, inlineRelationships),
|
||||
},
|
||||
|
||||
allocator: std.mem.Allocator,
|
||||
|
||||
pub fn next(self: Instance) !?TableWithRelations(TableShape, MetadataShape, inlineRelations) {
|
||||
pub fn next(self: Instance) !?TableWithRelationships(TableShape, MetadataShape, inlineRelationships) {
|
||||
return self.__interface.next(self.__interface.instance);
|
||||
}
|
||||
};
|
||||
|
@ -121,11 +121,11 @@ pub fn QueryResultReader(comptime TableShape: type, comptime MetadataShape: ?typ
|
|||
};
|
||||
}
|
||||
|
||||
/// Map query result to repository model structures, and load the given relations.
|
||||
pub fn ResultMapper(comptime Model: type, comptime TableShape: type, comptime MetadataShape: ?type, comptime repositoryConfig: _repository.RepositoryConfiguration(Model, TableShape), comptime inlineRelations: ?[]const _relations.Relation, comptime relations: ?[]const _relations.Relation) type {
|
||||
/// Map query result to repository model structures, and load the given relationships.
|
||||
pub fn ResultMapper(comptime Model: type, comptime TableShape: type, comptime MetadataShape: ?type, comptime repositoryConfig: _repository.RepositoryConfiguration(Model, TableShape), comptime inlineRelationships: ?[]const _relationships.Relationship, comptime relationships: ?[]const _relationships.Relationship) type {
|
||||
return struct {
|
||||
/// Map the query result to a repository result, with all the required relations.
|
||||
pub fn map(comptime withMetadata: bool, allocator: std.mem.Allocator, connector: _database.Connector, queryReader: QueryResultReader(TableShape, MetadataShape, inlineRelations)) !_repository.RepositoryResult(if (withMetadata) ModelWithMetadata(Model, MetadataShape) else Model) {
|
||||
/// Map the query result to a repository result, with all the required relationships.
|
||||
pub fn map(comptime withMetadata: bool, allocator: std.mem.Allocator, connector: _database.Connector, queryReader: QueryResultReader(TableShape, MetadataShape, inlineRelationships)) !_repository.RepositoryResult(if (withMetadata) ModelWithMetadata(Model, MetadataShape) else Model) {
|
||||
// Get result type depending on metadata
|
||||
const ResultType = if (withMetadata) ModelWithMetadata(Model, MetadataShape) else Model;
|
||||
|
||||
|
@ -144,32 +144,32 @@ pub fn ResultMapper(comptime Model: type, comptime TableShape: type, comptime Me
|
|||
while (try reader.next()) |rawModel| {
|
||||
// Parse each raw model from the reader.
|
||||
const model = try allocator.create(ResultType);
|
||||
(if (withMetadata) model.model else model.*) = try repositoryConfig.fromSql(toTableShape(TableShape, MetadataShape, inlineRelations, rawModel));
|
||||
(if (withMetadata) model.model else model.*) = try repositoryConfig.fromSql(toTableShape(TableShape, MetadataShape, inlineRelationships, rawModel));
|
||||
|
||||
// Map inline relations.
|
||||
if (inlineRelations) |_inlineRelations| {
|
||||
// If there are loaded inline relations, map them to the result.
|
||||
inline for (_inlineRelations) |relation| {
|
||||
// Map inline relationships.
|
||||
if (inlineRelationships) |_inlineRelationships| {
|
||||
// If there are loaded inline relationships, map them to the result.
|
||||
inline for (_inlineRelationships) |relationship| {
|
||||
// Read the inline related value.
|
||||
const relatedValue = (
|
||||
if (@field(rawModel, relation.field)) |relationVal|
|
||||
try relation.repositoryConfiguration().fromSql(relationVal)
|
||||
if (@field(rawModel, relationship.field)) |relationshipVal|
|
||||
try relationship.repositoryConfiguration().fromSql(relationshipVal)
|
||||
else null
|
||||
);
|
||||
|
||||
if (pointedType(@TypeOf(@field(model.*, relation.field)))) |childType| {
|
||||
if (pointedType(@TypeOf(@field(model.*, relationship.field)))) |childType| {
|
||||
if (relatedValue) |val| {
|
||||
// Allocate pointer value.
|
||||
@field(model.*, relation.field) = try mapperArena.allocator().create(childType);
|
||||
@field(model.*, relationship.field) = try mapperArena.allocator().create(childType);
|
||||
// Set pointer value.
|
||||
@field(model.*, relation.field).?.* = val;
|
||||
@field(model.*, relationship.field).?.* = val;
|
||||
} else {
|
||||
// Set NULL value.
|
||||
@field(model.*, relation.field) = null;
|
||||
@field(model.*, relationship.field) = null;
|
||||
}
|
||||
} else {
|
||||
// Set simple value.
|
||||
@field(model.*, relation.field) = relatedValue;
|
||||
@field(model.*, relationship.field) = relatedValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -189,11 +189,11 @@ pub fn ResultMapper(comptime Model: type, comptime TableShape: type, comptime Me
|
|||
}
|
||||
}
|
||||
|
||||
if (relations) |relationsToLoad| {
|
||||
inline for (relationsToLoad) |relation| {
|
||||
// Build query for the relation to get.
|
||||
const query: *relation.QueryType = @ptrCast(@alignCast(
|
||||
try relation.buildQuery(@ptrCast(models.items), allocator, connector)
|
||||
if (relationships) |relationshipsToLoad| {
|
||||
inline for (relationshipsToLoad) |relationship| {
|
||||
// Build query for the relationship to get.
|
||||
const query: *relationship.QueryType = @ptrCast(@alignCast(
|
||||
try relationship.buildQuery(@ptrCast(models.items), allocator, connector)
|
||||
));
|
||||
defer {
|
||||
query.deinit();
|
||||
|
@ -205,14 +205,14 @@ pub fn ResultMapper(comptime Model: type, comptime TableShape: type, comptime Me
|
|||
|
||||
// Create a map with related models.
|
||||
const RelatedModelsListType = std.ArrayList(@TypeOf(relatedModels.models[0].model));
|
||||
const RelatedModelsMapType = std.AutoHashMap(std.meta.FieldType(@TypeOf(relatedModels.models[0].metadata), .__zrm_relation_key), RelatedModelsListType);
|
||||
const RelatedModelsMapType = std.AutoHashMap(std.meta.FieldType(@TypeOf(relatedModels.models[0].metadata), .__zrm_relationship_key), RelatedModelsListType);
|
||||
var relatedModelsMap = RelatedModelsMapType.init(allocator);
|
||||
defer relatedModelsMap.deinit();
|
||||
|
||||
// Fill the map of related models, indexing them by the relation key.
|
||||
// Fill the map of related models, indexing them by the relationship key.
|
||||
for (relatedModels.models) |relatedModel| {
|
||||
// For each related model, put it in the map at the relation key.
|
||||
var modelsList = try relatedModelsMap.getOrPut(relatedModel.metadata.__zrm_relation_key);
|
||||
// For each related model, put it in the map at the relationship key.
|
||||
var modelsList = try relatedModelsMap.getOrPut(relatedModel.metadata.__zrm_relationship_key);
|
||||
|
||||
if (!modelsList.found_existing) {
|
||||
// Initialize the related models list.
|
||||
|
@ -225,7 +225,7 @@ pub fn ResultMapper(comptime Model: type, comptime TableShape: type, comptime Me
|
|||
|
||||
// For each model, at the grouped related models if there are some.
|
||||
for (models.items) |model| {
|
||||
@field(model, relation.field) = (
|
||||
@field(model, relationship.field) = (
|
||||
if (relatedModelsMap.getPtr(@field(model, repositoryConfig.key[0]))) |relatedModelsList|
|
||||
// There are related models, set them.
|
||||
try relatedModelsList.toOwnedSlice()
|
||||
|
|
|
@ -12,7 +12,7 @@ pub const RepositoryResult = repository.RepositoryResult;
|
|||
|
||||
pub const Insertable = insert.Insertable;
|
||||
|
||||
pub const relations = @import("relations.zig");
|
||||
pub const relationships = @import("relationships.zig");
|
||||
|
||||
pub const RawQueryParameter = _sql.RawQueryParameter;
|
||||
pub const RawQuery = _sql.RawQuery;
|
||||
|
|
|
@ -76,18 +76,18 @@ pub const UserRepository = zrm.Repository(User, User.Table, .{
|
|||
.fromSql = zrm.helpers.TableModel(User, User.Table).copyTableToModel,
|
||||
.toSql = zrm.helpers.TableModel(User, User.Table).copyModelToTable,
|
||||
});
|
||||
pub const UserRelations = UserRepository.relations.define(.{
|
||||
.picture = UserRepository.relations.one(MediaRepository, .{
|
||||
pub const UserRelationships = UserRepository.relationships.define(.{
|
||||
.picture = UserRepository.relationships.one(MediaRepository, .{
|
||||
.direct = .{
|
||||
.foreignKey = "picture_id",
|
||||
}
|
||||
}),
|
||||
|
||||
.info = UserRepository.relations.one(UserInfoRepository, .{
|
||||
.info = UserRepository.relationships.one(UserInfoRepository, .{
|
||||
.reverse = .{},
|
||||
}),
|
||||
|
||||
.messages = UserRepository.relations.many(MessageRepository, .{
|
||||
.messages = UserRepository.relationships.many(MessageRepository, .{
|
||||
.direct = .{
|
||||
.foreignKey = "user_id",
|
||||
},
|
||||
|
@ -121,8 +121,8 @@ pub const UserInfoRepository = zrm.Repository(UserInfo, UserInfo.Table, .{
|
|||
.fromSql = zrm.helpers.TableModel(UserInfo, UserInfo.Table).copyTableToModel,
|
||||
.toSql = zrm.helpers.TableModel(UserInfo, UserInfo.Table).copyModelToTable,
|
||||
});
|
||||
pub const UserInfoRelations = UserInfoRepository.relations.define(.{
|
||||
.user = UserInfoRepository.relations.one(UserRepository, .{
|
||||
pub const UserInfoRelationships = UserInfoRepository.relationships.define(.{
|
||||
.user = UserInfoRepository.relationships.one(UserRepository, .{
|
||||
.direct = .{
|
||||
.foreignKey = "user_id",
|
||||
},
|
||||
|
@ -157,14 +157,14 @@ pub const MessageRepository = zrm.Repository(Message, Message.Table, .{
|
|||
.fromSql = zrm.helpers.TableModel(Message, Message.Table).copyTableToModel,
|
||||
.toSql = zrm.helpers.TableModel(Message, Message.Table).copyModelToTable,
|
||||
});
|
||||
pub const MessageRelations = MessageRepository.relations.define(.{
|
||||
.user = MessageRepository.relations.one(UserRepository, .{
|
||||
pub const MessageRelationships = MessageRepository.relationships.define(.{
|
||||
.user = MessageRepository.relationships.one(UserRepository, .{
|
||||
.direct = .{
|
||||
.foreignKey = "user_id",
|
||||
}
|
||||
}),
|
||||
|
||||
.user_picture = MessageRepository.relations.one(MediaRepository, .{
|
||||
.user_picture = MessageRepository.relationships.one(MediaRepository, .{
|
||||
.through = .{
|
||||
.table = "example_users",
|
||||
.foreignKey = "user_id",
|
||||
|
@ -173,7 +173,7 @@ pub const MessageRelations = MessageRepository.relations.define(.{
|
|||
},
|
||||
}),
|
||||
|
||||
.medias = MessageRepository.relations.many(MediaRepository, .{
|
||||
.medias = MessageRepository.relationships.many(MediaRepository, .{
|
||||
.through = .{
|
||||
.table = "example_messages_medias",
|
||||
.joinModelKey = "message_id",
|
||||
|
@ -194,7 +194,7 @@ test "user picture media" {
|
|||
|
||||
var firstQuery = UserRepository.QueryWith(
|
||||
// Retrieve picture of users.
|
||||
&[_]zrm.relations.Relation{UserRelations.picture}
|
||||
&[_]zrm.relationships.Relationship{UserRelationships.picture}
|
||||
).init(std.testing.allocator, poolConnector.connector(), .{});
|
||||
try firstQuery.whereKey(1);
|
||||
defer firstQuery.deinit();
|
||||
|
@ -211,7 +211,7 @@ test "user picture media" {
|
|||
|
||||
var secondQuery = UserRepository.QueryWith(
|
||||
// Retrieve picture of users.
|
||||
&[_]zrm.relations.Relation{UserRelations.picture}
|
||||
&[_]zrm.relationships.Relationship{UserRelationships.picture}
|
||||
).init(std.testing.allocator, poolConnector.connector(), .{});
|
||||
try secondQuery.whereKey(3);
|
||||
defer secondQuery.deinit();
|
||||
|
@ -228,7 +228,7 @@ test "user picture media" {
|
|||
|
||||
var thirdQuery = UserRepository.QueryWith(
|
||||
// Retrieve picture of users.
|
||||
&[_]zrm.relations.Relation{UserRelations.picture}
|
||||
&[_]zrm.relationships.Relationship{UserRelationships.picture}
|
||||
).init(std.testing.allocator, poolConnector.connector(), .{});
|
||||
try thirdQuery.whereKey(5);
|
||||
defer thirdQuery.deinit();
|
||||
|
@ -244,7 +244,7 @@ test "user picture media" {
|
|||
|
||||
var fourthQuery = UserRepository.QueryWith(
|
||||
// Retrieve picture of users.
|
||||
&[_]zrm.relations.Relation{UserRelations.picture}
|
||||
&[_]zrm.relationships.Relationship{UserRelationships.picture}
|
||||
).init(std.testing.allocator, poolConnector.connector(), .{});
|
||||
try fourthQuery.whereKey(19);
|
||||
defer fourthQuery.deinit();
|
||||
|
@ -267,7 +267,7 @@ test "user has info" {
|
|||
|
||||
var firstQuery = UserRepository.QueryWith(
|
||||
// Retrieve info of users.
|
||||
&[_]zrm.relations.Relation{UserRelations.info}
|
||||
&[_]zrm.relationships.Relationship{UserRelationships.info}
|
||||
).init(std.testing.allocator, poolConnector.connector(), .{});
|
||||
try firstQuery.whereKey(2);
|
||||
defer firstQuery.deinit();
|
||||
|
@ -284,7 +284,7 @@ test "user has info" {
|
|||
|
||||
var secondQuery = UserRepository.QueryWith(
|
||||
// Retrieve info of users.
|
||||
&[_]zrm.relations.Relation{UserRelations.info}
|
||||
&[_]zrm.relationships.Relationship{UserRelationships.info}
|
||||
).init(std.testing.allocator, poolConnector.connector(), .{});
|
||||
try secondQuery.whereKey(1);
|
||||
defer secondQuery.deinit();
|
||||
|
@ -299,7 +299,7 @@ test "user has info" {
|
|||
|
||||
var thirdQuery = UserInfoRepository.QueryWith(
|
||||
// Retrieve info of users.
|
||||
&[_]zrm.relations.Relation{UserInfoRelations.user}
|
||||
&[_]zrm.relationships.Relationship{UserInfoRelationships.user}
|
||||
).init(std.testing.allocator, poolConnector.connector(), .{});
|
||||
try thirdQuery.whereKey(2);
|
||||
defer thirdQuery.deinit();
|
||||
|
@ -326,7 +326,7 @@ test "user has many messages" {
|
|||
|
||||
var firstQuery = UserRepository.QueryWith(
|
||||
// Retrieve messages of users.
|
||||
&[_]zrm.relations.Relation{UserRelations.messages}
|
||||
&[_]zrm.relationships.Relationship{UserRelationships.messages}
|
||||
).init(std.testing.allocator, poolConnector.connector(), .{});
|
||||
try firstQuery.whereKey(1);
|
||||
defer firstQuery.deinit();
|
||||
|
@ -354,7 +354,7 @@ test "user has many messages" {
|
|||
|
||||
var secondQuery = UserRepository.QueryWith(
|
||||
// Retrieve messages of users.
|
||||
&[_]zrm.relations.Relation{UserRelations.messages}
|
||||
&[_]zrm.relationships.Relationship{UserRelationships.messages}
|
||||
).init(std.testing.allocator, poolConnector.connector(), .{});
|
||||
try secondQuery.whereKey(5);
|
||||
defer secondQuery.deinit();
|
||||
|
@ -380,7 +380,7 @@ test "message has many medias through pivot table" {
|
|||
|
||||
var firstQuery = MessageRepository.QueryWith(
|
||||
// Retrieve medias of messages.
|
||||
&[_]zrm.relations.Relation{MessageRelations.medias}
|
||||
&[_]zrm.relationships.Relationship{MessageRelationships.medias}
|
||||
).init(std.testing.allocator, poolConnector.connector(), .{});
|
||||
try firstQuery.whereKey(1);
|
||||
defer firstQuery.deinit();
|
||||
|
@ -397,7 +397,7 @@ test "message has many medias through pivot table" {
|
|||
|
||||
var secondQuery = MessageRepository.QueryWith(
|
||||
// Retrieve medias of messages.
|
||||
&[_]zrm.relations.Relation{MessageRelations.medias}
|
||||
&[_]zrm.relationships.Relationship{MessageRelationships.medias}
|
||||
).init(std.testing.allocator, poolConnector.connector(), .{});
|
||||
try secondQuery.whereKey(6);
|
||||
defer secondQuery.deinit();
|
||||
|
@ -423,7 +423,7 @@ test "message has many medias through pivot table" {
|
|||
|
||||
var thirdQuery = MessageRepository.QueryWith(
|
||||
// Retrieve medias of messages.
|
||||
&[_]zrm.relations.Relation{MessageRelations.medias}
|
||||
&[_]zrm.relationships.Relationship{MessageRelationships.medias}
|
||||
).init(std.testing.allocator, poolConnector.connector(), .{});
|
||||
try thirdQuery.whereKey(4);
|
||||
defer thirdQuery.deinit();
|
||||
|
@ -448,7 +448,7 @@ test "message has one user picture URL through users table" {
|
|||
|
||||
var firstQuery = MessageRepository.QueryWith(
|
||||
// Retrieve user pictures of messages.
|
||||
&[_]zrm.relations.Relation{MessageRelations.user_picture}
|
||||
&[_]zrm.relationships.Relationship{MessageRelationships.user_picture}
|
||||
).init(std.testing.allocator, poolConnector.connector(), .{});
|
||||
try firstQuery.whereKey(1);
|
||||
defer firstQuery.deinit();
|
||||
|
@ -464,7 +464,7 @@ test "message has one user picture URL through users table" {
|
|||
|
||||
var secondQuery = MessageRepository.QueryWith(
|
||||
// Retrieve user pictures of messages.
|
||||
&[_]zrm.relations.Relation{MessageRelations.user_picture}
|
||||
&[_]zrm.relationships.Relationship{MessageRelationships.user_picture}
|
||||
).init(std.testing.allocator, poolConnector.connector(), .{});
|
||||
try secondQuery.whereKey(4);
|
||||
defer secondQuery.deinit();
|
||||
|
@ -476,4 +476,4 @@ test "message has one user picture URL through users table" {
|
|||
try std.testing.expect(secondResult.models[0].user_picture == null);
|
||||
}
|
||||
|
||||
//TODO try to load all one relations types in another query (with buildQuery).
|
||||
//TODO try to load all one relationships types in another query (with buildQuery).
|
||||
|
|
|
@ -33,8 +33,8 @@ test "belongsTo" {
|
|||
|
||||
// Build a query of submodels.
|
||||
var myQuery = repository.MySubmodelRepository.QueryWith(
|
||||
// Retrieve parents of submodels from relation.
|
||||
&[_]zrm.relations.Relation{repository.MySubmodelRelations.parent}
|
||||
// Retrieve parents of submodels from relationship.
|
||||
&[_]zrm.relationships.Relationship{repository.MySubmodelRelationships.parent}
|
||||
).init(std.testing.allocator, poolConnector.connector(), .{});
|
||||
defer myQuery.deinit();
|
||||
|
||||
|
@ -64,8 +64,8 @@ test "hasMany" {
|
|||
|
||||
// Build a query of submodels.
|
||||
var myQuery = repository.MyModelRepository.QueryWith(
|
||||
// Retrieve parents of submodels from relation.
|
||||
&[_]zrm.relations.Relation{repository.MyModelRelations.submodels}
|
||||
// Retrieve parents of submodels from relationship.
|
||||
&[_]zrm.relationships.Relationship{repository.MyModelRelationships.submodels}
|
||||
).init(std.testing.allocator, poolConnector.connector(), .{});
|
||||
defer myQuery.deinit();
|
||||
|
|
@ -68,8 +68,8 @@ pub const MySubmodelRepository = zrm.Repository(MySubmodel, MySubmodelTable, .{
|
|||
.toSql = &submodelToSql,
|
||||
});
|
||||
|
||||
pub const MySubmodelRelations = MySubmodelRepository.relations.define(.{
|
||||
.parent = MySubmodelRepository.relations.one(MyModelRepository, .{
|
||||
pub const MySubmodelRelationships = MySubmodelRepository.relationships.define(.{
|
||||
.parent = MySubmodelRepository.relationships.one(MyModelRepository, .{
|
||||
.direct = .{
|
||||
.foreignKey = "parent_id",
|
||||
},
|
||||
|
@ -126,8 +126,8 @@ pub const MyModelRepository = zrm.Repository(MyModel, MyModelTable, .{
|
|||
.toSql = &modelToSql,
|
||||
});
|
||||
|
||||
pub const MyModelRelations = MyModelRepository.relations.define(.{
|
||||
.submodels = MyModelRepository.relations.many(MySubmodelRepository, .{
|
||||
pub const MyModelRelationships = MyModelRepository.relationships.define(.{
|
||||
.submodels = MyModelRepository.relationships.many(MySubmodelRepository, .{
|
||||
.direct = .{
|
||||
.foreignKey = "parent_id",
|
||||
}
|
||||
|
|
|
@ -5,6 +5,6 @@ comptime {
|
|||
_ = @import("repository.zig");
|
||||
_ = @import("composite.zig");
|
||||
_ = @import("sessions.zig");
|
||||
_ = @import("relations.zig");
|
||||
_ = @import("relationships.zig");
|
||||
_ = @import("example.zig");
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ test "session with rolled back transaction and savepoint" {
|
|||
|
||||
try session.beginTransaction();
|
||||
|
||||
|
||||
|
||||
// First UPDATE in the transaction.
|
||||
{
|
||||
var firstUpdate = repository.MyModelRepository.Update(struct {
|
||||
|
|
Loading…
Reference in a new issue