Forum OpenACS Development: group_types: why not referenced in groups

I am going over the basic kernel data model and I noticed a few things. One is that group_types is not referenced by groups. To find a list of groups of a given type you have to use the acs_objects table, and look at the object_type.

From what it appears the reason is that groups have a "default join policy", otherwise the data model for acs_object_types covers everything else.

Couldn't this column be moved to acs_object_types and set to null in the case the type wasn't a group?

Would denormalizing the groups table to include a reference from group_type to the acs_object_types(object_type) be useful?

Collapse
Posted by Don Baccus on
I'd vote for the second rather than kludge acs_object_types with a field set null if the type isn't a group type.  Kludges like this are a bit like losing your virginity, there's no going back ... someone will ask for the same kludge for some other type's special case needs and on and on :)

But before denormalizing it's normal to evaluate whether or not doing the denormalization will improve performance considerably.  Will it?  Remember we will need an index on the referencing column in group_type, otherwise deleting object_types will do a sequential scan on group_types when the foreign key check is made so an error or cascade op can be triggered.

So if all this is being used for is to grab the group type's default join policy I'd question if the denormalization would be worth it ...

Collapse
Posted by Barry Books on
I think (I could be wrong) that the join policy in group_types is the default join policy for the group type.

I looked at this a little bit yesterday but the group type pages are so slow on my machine they are almost unusable. I believe the group type pages create tables for the group types also and it's possible to add columns to these via the interface. You can also get a list of group id's by group type from these tables.

Looking at this another way, is this really a kludge to get around the fact that object_types and attrbiutes are not objects. If they were would join policy just be another attribute of group_type object.

I've found it useful to get what group types a user is in. I usally do that when the regular permission system would be too slow. If I know the user is in a group with admin permission then I don't need to check every record. That query is not all that fast either.

I've been thinking about partitioning the acs_objects table by object_type but it's difficult because you really need to partition by some supertype. It might be nice to have a generlized method for denormalizing data like this because it would eliminate the need to join with acs_objects. It's not as transparent as partitions but it's not Oracle dependent and it solves the problem better.

Collapse
Posted by Tom Jackson on

I guess what I was getting at overall is this:

  • If the default join policy can be modified per group, then why do we need a whole separate table to hold this "convenience" information?
  • Adding a column to groups with the group_type->object_type reference would make it really easy to get groups of a given type. You don't need to do this, but it would save a join.
  • Maybe the join policy default could be inherited from the package instance under which the group is created. I noticed, with amazement that if you create groups via pl procedures they don't have a package_id associated with them, and they therefore don't show up in the subsite admin ui of any subsite, not even the one mounted on '/'. Othewise, a group with no associated package_id would have a default join policy of closed.
  • There should be some admin interface, somewhere that actually looks at what is in the database instead of qualifying the query with things like package_ids and permissions to view. (That is what the permission check on the package_id is supposed to take care of in one simple check.) Queries like the following on group-types/one:
        select my_view.group_name, my_view.group_id
        from (select DISTINCT g.group_name, g.group_id
               from acs_objects o, groups g,
                    application_group_element_map app_group, 
                    all_object_party_privilege_map perm
              where perm.object_id = g.group_id
                and perm.party_id = :user_id
                and perm.privilege = 'read'
                and g.group_id = o.object_id
                and o.object_type = :group_type
                and app_group.package_id = :package_id
                and app_group.element_id = g.group_id
              order by g.group_name, g.group_id) my_view 
        limit 26
    
    Okay, that is a completely separate issue, sorry.

Question is: is any of this useful, or just a pain since things basically work anyway, and when would I get time to make changes that would probably affect vendor packages?

Collapse
Posted by Don Baccus on
I've found it useful to get what group types a user is in. I usally do that when the regular permission system would be too slow. If I know the user is in a group with admin permission then I don't need to check every record. That query is not all that fast either.

Is this still true with the new permissions code, especially since you say the group membership query's not particularly fast either? Checking permissions is more flexible, among other things if you inherit from parent packages normally the sitewide admin will always be able to admin things without being explicitly added to your various admin groups which most of us would consider a Almost Always A Good Thing.

Collapse
Posted by Barry Books on
I'm working on upgrading to ACS HEAD. Since I'm moving to 9i and I thought now woould be a good time. Also the 4.2 permission system is not fast enough to run on queries that return many rows. I'm hoping the new one is.
Collapse
Posted by Dave Bauer on
Barry,

If you mean caling acs_permission__permission_p in the where clause, it still is slow but not as slow as it was before. Not necessarily because the function itself is slow, rather it is always slow to use a function in the where clause of a query.

Collapse
Posted by Dirk Gomez on

The Oracle Magazine May 2003 had an article on the slowness of PL/SQL functions in SQL functions. It can be found here: http://otn.oracle.com/oramag/oracle/03-may/o33asktom.html and it's the answer to the very question ("I created a PL/SQL function to compute the distance between two points, but it takes over one-half hour to execute when I call it from SQL. ")

Interesting enough: the slow PL/SQL function here doesn't access the database at all, the whole time gets waste by context switches between the SQL and the PL/SQL engine.

Collapse
Posted by Don Baccus on
Right which is why I keep telling people that with the new permissions system, don't call permission_p in your where clause but use the acs_object_party_privilege_map (or whatever it's called) with an "exists" subselect instead.

Only call permission_p if you need to determine permissions on rows that are returned.  Preferably when you're not returning a lot of rows.

Barry ... the 4.6 and later permissions calls are much, much faster than 4.2 when there are lots of objects, deep permissions hierarchies, etc.

Collapse
Posted by Barry Books on
I'm mostly interested in being able to join with the view. Having permission_p being faster would be nice but on a page that calls it once it's fast enough. I'm planning on doing some beachmarks but I'll also be switching hardware when I upgrade so the results may be skewed by that.