I ran your query via the Partner API.
select user.id, user.Email, user.FirstName, user.LastName, user.profile.name, user.Username, user.IsActive FROM user, user.profile
One small aside note about the query, you don't need the ", user.profile" in the from clause. SOQL will do the reference join for you without it.
The first sObject that came back in the query result had the following XmlElements in the Any
property array:
0: "<sf:Id xmlns:sf=\"urn:sobject.partner.soap.sforce.com\">005400000000001AAK</sf:Id>"
1: "<sf:Email xmlns:sf=\"urn:sobject.partner.soap.sforce.com\">a.user@example.com</sf:Email>"
2: "<sf:FirstName xmlns:sf=\"urn:sobject.partner.soap.sforce.com\">A</sf:FirstName>"
3: "<sf:LastName xmlns:sf=\"urn:sobject.partner.soap.sforce.com\">User</sf:LastName>"
4: "<sf:Profile
xsi:type=\"sf:sObject\"
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
xmlns:sf=\"urn:sobject.partner.soap.sforce.com\">
<sf:type>Profile</sf:type>
<sf:Id xsi:nil=\"true\" />
<sf:Name>Custom: Admin</sf:Name>
</sf:Profile>"
5: "<sf:Username xmlns:sf=\"urn:sobject.partner.soap.sforce.com\">robert.doek@example.com</sf:Username>"
6: "<sf:IsActive xmlns:sf=\"urn:sobject.partner.soap.sforce.com\">false</sf:IsActive>"
So to get to the Profile name element you will need to traverse via the Profile XmlElement. How you do that will depend on your language.
You might take a look at SOQL polymorphism.
Since the parent object referenced by UserOrGroupId could be either a User or a Group, normal SOQL won't let you reference any parent fields, similar to attempting to reference fields via WhatId on an Event. SOQL's TYPEOF keyword should allow you to perform the query you want.
REVISED
The TYPEOF keyword would still give you the query you want, but I apologize for overlooking it's general unavailability. Without this being a widely available feature, I do not think there is another way to create the single query on GroupMember.
...
Map<Id, Group> groupMap = new Map<Id, Group>([
Select Id, Name
From Group
Where Type = 'Queue'
]);
List<GroupMember> groupMembers = [
Select GroupId, UserOrGroupId
From GroupMember
Where GroupId In :groupMap.keySet()
];
Set<Id> userOrGroupIds = new Set<Id>();
for (GroupMember member : groupMembers) {
userOrGroupIds.add(member.UserOrGroupId);
}
Map<Id, User> userMap = new Map<Id, User>([
Select Id, LastName
From User
Where Id In :userOrGroupIds
]);
Map<Id, List<User>> groupIdToUsers = new Map<Id, List<User>>();
for (Id groupId : groupMap.keySet()) {
groupIdToUsers.put(groupId, new List<User>());
}
for (GroupMember member : groupMembers) {
if (userMap.containsKey(member.UserOrGroupId)) {
groupIdToUsersMap.get(member.GroupId).add(userMap.get(member.UserOrGroupId));
}
}
...
With this, you can loop over the values of groupMap and pull the list of Users from groupIdToUsers.
You can alter your filters and limits in the queries as you see fit, especially if you are expecting a large number of Users. There are also certainly other ways you could write this.
If you want to track which Groups are also members of other Groups, you would need to maintain a separate Group map that gets processed similarly to User map.
Best Answer
If you don't want to burn a SOQL Statement and you're working with an SObject, you can use this approach:
Formula field (named, say, "CurrentUserProfile) on an object that has this code:
$UserProfile.Name
In your trigger, you can refer to the variable;
for(Object__c obj :triggerNew) { System.debug('Current User Profile: ' + obj.CurrentuserProfile__c); }