Custom fields design doc

Sean McAfee etzwane at schwag.org
Fri May 23 02:32:23 UTC 2003


Gervase Markham <gerv at mozilla.org> wrote:
>Sean McAfee wrote:
>> field_id integer auto_increment primary key,
>> field_name tinytext not null,
>> display_name tinytext not null,

>If this isn't in templates, it can't be localised - i.e. you can only 
>have a single value, no matter how many nationalities of people use your 
>Bugzilla. I still think we should have a mechanism where it uses 
>field_name to begin with, and you then define display names in templates 
>on a per-language basis...

By this time, my desire to avoid requiring the admin to twiddle templates is
well-known.  Hmmm.  OK, how about storing display names in a table like
this:

cf_names
--------
field_id integer not null references custom_fields(field_id),
locale tinytext not null,
display_name tinytext not null

A "Current locale:" selection field could be added to the main custom
fields admin screen.  Changing it would cause all of the display names to be
shown according to the new locale.

>> The field_type column is 'i' for integer fields, 'c' for short string
>> fields, 'C' for long string fields, 'd' for date-only fields, 'D' for
>> date-time fields, 's' for single-selection fields, and 'S' for
>> multiselection fields.

>The following make more sense to me:
>i: integer
>s: string
>l: long string
>d: date
>t: date-time
>e: single-select (e for enum; OK, this one's a bit iffy)
>m: multi-select

>The upper/lower case distinction doesn't always mean the same thing, so 
>is a bit confusing IMO.

Well, perhaps.  I was trying to let the case of the type take the place of
my old 'extended' field.

>> cf_groups
>> ---------
>> group_id integer auto_increment primary key,
>> group_name tinytext
>> 
>> This table contains one row for every custom field group.  The name
>> may be NULL for reasons described below.

>I'm having trouble understanding this proposal, because of one big 
>question: what's a custom field group?

It's my proposed mechanism for implementing field sharing.  Say a group
G contains fields Foo, Bar, and Baz.  Then every project that contains the
group G also has fields Foo, Bar, and Baz.  I probably didn't describe the
concept in enough detail, but I hoped the editcustomfields.html example page
I provided would get the idea across.

>> cf_product_members
>> ------------------
>> product smallint references products(id),
>> group_id integer not null references cf_groups(group_id),
>> display_index integer not null,
>> index (product)

>"display_index" should have the same name as the fields which do the 
>same thing in other tables (can't remember what it is offhand.)

Would that be "sortkey"?

>> cf_selections
>> -------------
>> selection_id integer auto_increment primary key,
>> unset_label tinytext not null
>> 
>> The unset_label column is the text which represents the "empty set"
>> value of single-selection fields.
>> 
>> cf_selection_labels
>> -------------------
>> label_id integer auto_increment primary key,
>> selection_id integer not null references cf_selections(selection_id),
>> label_index integer not null,
>> label tinytext not null,
>> index (selection_id)

>Why can these two tables not be combined?

Because then the unset_label column would have to be duplicated.

>> For each single-selection field, there is one row in the table.  The
>> selection_id is NULL if the field is unset; otherwise it references a
>> row in the cf_selection_labels table.

>Surely "there's no row present if the field is unset"? This matches the 
>behaviour for multi-selects.

Yes, I was erroneously conflating the UI behavior (where everything always
needs a label) with the DB behavior.

>> The following six tables hold bug activity data.

>Dude, scrap this! Use our current tables for bug activity data. Please! 
>:-) Store the name of the field, what it changed from, and what it 
>changed to, just like now. That's fine. Really.

I'm reluctant to do this for a few reasons.  First, the more orthogonal
the custom fields implementation is to the core, the less chance there
is of a buggy interaction between the two.  Second, queries against bug
activity would be complicated by cast functions if everything is stored
as a string.  Finally, the current activity table (bugs_activity) logs
changes in tinytext columns, which aren't big enough to log changes in
long string fields or some multiselect fields.  Even if the columns were
widened to the text type, multiselect changes could potentially still be too
large for them, as I've described in a previous message.

>> FILE SYSTEM
>> ===========
>> All custom-field-related templates go in the directory
>> $BUGZILLA_ROOT/template/en/default/custom.

>That's rather confusing, because we have a template/en/custom for custom 
>templates. You could have "custom-fields", which would be better, but 
>otherwise they'd just live in whichever part of the template tree they 
>were relevant to.

OK, custom-fields it is.

>> ADMINISTRATION
>> ==============
>> Each page contains a single form, which always contains a hidden field
>> called "context".

>We call this "action" everywhere else.

"context" is more intuitive to me, but oh well, viva consistency.

>> Initial page
>> ------------
>> Context:  choose-scope
>> Template: template/en/default/custom/choose-scope.html.tmpl
>> 
>> The user may select a scope via either of the following three elements:

>What is a scope?

A project, a group, or the global scope.

>And, importantly, if this is a design document, there is no place in it 
>for code. It's just obfuscating, and premature detail.

If I hadn't written it, I'd agree with you, at first glance.  However,
I found that creating those templates (which aren't code, not exactly)
helped me greatly in refining the design.  As just one example, in theory
it's sufficient to copy the "type" column from the custom_fields table
into a template-accessible hash, but in writing the template I found
that it's clearer to abstract the type information into several distinct
members--"is_integer", "is_string", etc.  Maybe this design approach
is peculiar to template programming; the template isn't in the realm
of the design document, strictly speaking, but the method of generating
the backend data on which the template depends is.

>If you are in fact in the middle of implementing this exactly as you've 
>designed it above, you might as well say so and be done with it :-)

*Now* I'm in the middle of implementing it, but at the time I posted the
document I hadn't yet begun.  Scout's honor!


-- 
Sean McAfee -- etzwane at schwag.org



More information about the developers mailing list