diff --git a/src/result.zig b/src/result.zig index 654ff09..b9cbed7 100644 --- a/src/result.zig +++ b/src/result.zig @@ -150,12 +150,27 @@ pub fn ResultMapper(comptime Model: type, comptime TableShape: type, comptime Me if (inlineRelations) |_inlineRelations| { // If there are loaded inline relations, map them to the result. inline for (_inlineRelations) |relation| { - // Set the read inline relation value. - @field(model.*, relation.field) = ( + // Read the inline related value. + const relatedValue = ( if (@field(rawModel, relation.field)) |relationVal| try relation.repositoryConfiguration().fromSql(relationVal) else null ); + + if (pointedType(@TypeOf(@field(model.*, relation.field)))) |childType| { + if (relatedValue) |val| { + // Allocate pointer value. + @field(model.*, relation.field) = try mapperArena.allocator().create(childType); + // Set pointer value. + @field(model.*, relation.field).?.* = val; + } else { + // Set NULL value. + @field(model.*, relation.field) = null; + } + } else { + // Set simple value. + @field(model.*, relation.field) = relatedValue; + } } } @@ -230,3 +245,16 @@ pub fn ResultMapper(comptime Model: type, comptime TableShape: type, comptime Me } }; } + +/// Get pointed type of the given type. +/// Return NULL if the type is not a pointer. +fn pointedType(@"type": type) ?type { + return switch (@typeInfo(@"type")) { + .Pointer => |ptr| ptr.child, + .Optional => |opt| switch (@typeInfo(opt.child)) { + .Pointer => |ptr| ptr.child, + else => null, + }, + else => null, + }; +} diff --git a/tests/example.zig b/tests/example.zig index 88c7463..a4c9e0d 100644 --- a/tests/example.zig +++ b/tests/example.zig @@ -110,8 +110,7 @@ pub const UserInfo = struct { user_id: i32, birthdate: i64, - //TODO is there a way to solve the "struct 'example.User' depends on itself" error when adding this relation? - // user: ?User = null, + user: ?*User = null, }; pub const UserInfoRepository = zrm.Repository(UserInfo, UserInfo.Table, .{ .table = "example_users_info", @@ -123,11 +122,11 @@ pub const UserInfoRepository = zrm.Repository(UserInfo, UserInfo.Table, .{ .toSql = zrm.helpers.TableModel(UserInfo, UserInfo.Table).copyModelToTable, }); pub const UserInfoRelations = UserInfoRepository.relations.define(.{ - // .user = UserInfoRepository.relations.one(UserRepository, .{ - // .direct = .{ - // .foreignKey = "user_id", - // }, - // }), + .user = UserInfoRepository.relations.one(UserRepository, .{ + .direct = .{ + .foreignKey = "user_id", + }, + }), }); pub const Message = struct { @@ -295,6 +294,24 @@ test "user has info" { try std.testing.expectEqual(1, secondResult.models.len); try std.testing.expect(secondResult.models[0].info == null); + + + + var thirdQuery = UserInfoRepository.QueryWith( + // Retrieve info of users. + &[_]zrm.relations.Relation{UserInfoRelations.user} + ).init(std.testing.allocator, poolConnector.connector(), .{}); + try thirdQuery.whereKey(2); + defer thirdQuery.deinit(); + + var thirdResult = try thirdQuery.get(std.testing.allocator); + defer thirdResult.deinit(); + + try std.testing.expectEqual(1, thirdResult.models.len); + try std.testing.expectEqual(876348000000000, thirdResult.models[0].birthdate); + try std.testing.expect(thirdResult.models[0].user != null); + try std.testing.expectEqual(2, thirdResult.models[0].user.?.id); + try std.testing.expectEqualStrings("madeorsk", thirdResult.models[0].user.?.name); }