For a system I am currently building, the following two scenarios occur:
My permissions system is the perennial favorite of attaching permissions to roles, and roles to users, but with a twist: permissions may be applied to any asset at any tier, and there are 4 "Tiers", numbered 0 through 3. As such, the role assignment table is 5 fields long: asset tier, asset ID, role ID, user ID, and a flag for "disabled." This "Tier/ID" system is also used in assigning users to a "Home Asset".
The unfortunate side effect of this system is that it is generally far simpler to resolve my these asset references in the application itself, instead of in the SQL (I know it would be possible to do, but it would result in some seriously ugly queries). Is there a better way to represent this sort of relationship? Is this an acceptable way of representing this relationship?
Side note: the tables for the assets themselves (they are hierarchal) are normalized, with foreign key references pointing from child to parent (e.g. Tier 3 contains info about Tier 2, etc), so once a single asset is pinned down it is very simple to locate its children and ancestors.
Similar problem, but different data context: At the lowest tier, devices can be "attached." Devices are also allowed to be placed onto a graphical representation (like a map), and their arrangement information is stored in the database. Graphical references (also called "points") should point at a real device, but a real device may not point at a graphical reference.
At present, there is a single reference table to all "points" (which represent devices) with information for their display layout, location, size, etc. I can identify three possible things to do from here:
- Create a series of normalized tables to represent individual devices, and use a similar "device type / device ID" system to look them up, and store this information in the "points" table; this will still require the application to do intermediary work in resolving those references to actual devices in their respective tables
- Create a series of normalized tables, and point them at the "points" table; this solution probably won't require the application to dereference the points data, but will require that all device tables be scanned for any Tier 3 object.
- Using the points table as a guideline, add all of the relevant display data to each respective normalized table. While this would prevent having to resolve any lookups at all, it will still require that I scan every device table, and is also extremely intolerant to any changes in how the points data must be stored compared to the other solutions.
Is this problem already solved and I just didn't get the memo? Is there a standard design addressing this problem, or should I just assume that I will have to resolve these references myself?
Note: With respect to problem two, I have deemed the following two solutions to be horrible and I will not consider them (barring some crazy, amazing evidence that it is the best way, which I'm fairly sure it isn't):
- Store all the information about each device (in a serialized array or some such mechanism) in the points table itself. This has the obvious problem of being completely unsearchable and defying normal form
- Store all devices in a single, generic table. Unfortunately, these devices are all extremely different in the type of data they provide, as well as how they must be accessed, and doing so in one table would require, last time I tried working it out on paper, at least 30 (and probably more) columns, more than half of which would be null for every row.
Any solutions are requested and appreciated, though I am specifically looking for existing patterns and/or normalized schemas which address this issue, if any exist. If you know for a fact that it is the correct answer, "No" will suffice and I will continue to use the application layer to resolve these references. It has not been a problem yet, I just prefer to know I'm not forging a path in the wrong direction when someone has already solved this/these problem(s). Thanks in advance.
EDIT: Permissions/Asset Schema
Tier 0 is actually implied and not in the database, but some things are registered as Tier 0 (Asset ID 0)
Tier 1:
id int(5) unsigned not null primary key auto_increment,
name varchar(32) not null,
disabled tinyint(1) unsigned not null,
Tier 2:
id int(5) unsigned not null primary key auto_increment,
parentId int(5) unsigned not null,
name varchar(32) not null,
abbr varchar(16) not null,
disabled tinyint(1) unsigned not null,
foreign key (parentId) references tier1(id)
Tier 3:
id int(5) unsigned not null primary key auto_increment,
parentId int(5) unsigned not null,
name varchar(32) not null,
abbr varchar(16) not null,
disabled tinyint(1) unsigned not null,
foreign key (parentId) references tier2(id)
Permissions:
id int(5) unsigned not null primary key auto_increment,
permission_key varchar(16) not null,
permission_desc varchar(128) not null
Roles:
id int(5) unsigned not null primary key auto_increment,
name varchar(32) not null,
tier1_id int(5) unsigned not null,
disabled tinyint(1) unsigned not null,
foreign key (tier1_id) references tier1(id)
Role_Permissions:
role_id int(5) unsigned not null,
permission_id int(5) unsigned not null,
disabled tinyint(1) unsigned not null,
primary key (role_id, permission_id),
foreign key (role_id) references roles(id),
foreign key (permission_id) references permissions(id)
User_Role_Permissions:
tier_id tinyint(1) unsigned not null,
asset_id int(5) unsigned not null,
user_id int(5) unsigned not null,
role_id int(5) unsigned not null,
disabled tinyint(1) unsigned not null,
primary key (tier_id, asset_id, user_id, role_id),
foreign key (user_id) references users(id),
foreign key (role_id) references roles(id)