Preliminary note : There are more urgent D7 Fields tasks. This post is mainly to state where we are and initiate discussion, or at least get initial thoughts written down somewhere. I do not intend nor have the wits to tackle this on my own. Obviously, the Field API gang, David Strauss, Crell, merlinofchaos are highly welcome to chime in.

Quick introduction/reminder: The storage part of the Fields API relies on the notion of 'storage engine', making actual storage potentially swappable by simply adding an additional 'storage engine' module. "Usual" storage in local SQL tables is just the default engine, shipped with core. The goal, outlined during the DADS and FiC sprints, was to allow remote and/or non relational storage (data repository behind a SOAP interface, CouchDB...). Work during and since the FiC sprint focused on laying the bases by cleanly separating and abstracting out the storage part, leaving out the 'swappable' aspects for later.

Right now, the storage engine is a site-wide variable, which means all fields on all entities use the same storage. This pretty much invalidates the use cases : If 'body as field' gets in - and we sure hope it (and more like it) does, who wants to store all his node bodies or node terms in a remote backend ?

Discussed this a little with Crell on http://www.palantir.net/blog/remote-data-drupal-museums-and-web-2009 (see the end of the article, and the first comments), then on IRC.

The main issue with allowing several storage backends being : Views cannot filter/sort by on two separate datasets.
There are two ways swappable storage backends could be implemented :

1) per object type backend : all fields on a given object type use the same backend. Node fields are local, 'artwork' fields are remote (since the DADS sprint, 'artwork' is the generic example of an object type that primary lives remotely, but that needs to appear as 'content' of the drupal site - think a museum site that exposes its collections)
A fieldable entity defines which storage engine it uses, and we need to restrict field sharing across a given object type, or at least across object types that use the same storage.

Maps rather simply for Views : depending on the 'base table' (entity) of the view, you get a single storage engine to query against for all the fields (provided it also exposes a Views query builder...)

2) per field backend : $field['storage'] defines which storage backend is used. You can mix local and remote data on the same object. hook_field_storage_(load|write) only care about fields where $field['storage'] == myself.

I initially thought this would be unmanageable for Views, but Crell sees it this way :
- Base objects need a primary storage anyway (at least to hold the object primary id, and to serve as a Views primary 'table'). Nodes, users are local, Artwork is remote.
- then Views can simply exclude any fields that do not specify that same engine. So a node view could only filter and order by local fields, not remote ones, while an artwork view could only filter and order by remote fields, not fivestar ratings.

Storage engines as we currently define them now only relate to fields. Right now there's no way to know that they can also store and serve primary object keys and say 'this field and this object type use the same storage backend, so you can use this field in this View'. Maybe it's just as in option 1), a fieldable entity defines which storage engine it uses, and the rest is up to the engine's Views layer, dunno for sure.

CommentFileSizeAuthor
#75 field-multiple-storage-443422-75.patch88.48 KBbjaspan
#74 field-multiple-storage-443422-73.patch87.98 KBbjaspan
#69 field-multiple-storage-443422-69.patch86.48 KBbjaspan
#66 field-multiple-storage-443422-66.patch86.41 KBbjaspan
#61 field_multiple_storage-443422-61.patch82.34 KByched
#61 field_multiple_storage-443422-61_test_storage.patch82.34 KByched
#59 field_multiple_storage-443422-60.patch80.5 KByched
#59 field_multiple_storage-443422-60_test_storage.patch80.5 KByched
#58 field_multiple_storage-443422-59.patch75.12 KByched
#57 field_multiple_storage-443422-58.patch74.25 KByched
#55 field_multiple_storage-443422-56.patch74.19 KByched
#51 field_multiple_storage-443422-50.patch71.54 KByched
#48 field_multiple_storage-443422-48.patch72.14 KByched
#46 field_multiple_storage-443422-46.patch70.09 KByched
#44 field_multiple_storage-443422-44.patch68.29 KByched
#42 field_multiple_storage-443422-42.patch74.47 KByched
#40 field_multiple_storage-443422-40.patch74.51 KByched
#37 field_multiple_storage-443422-37.patch68.1 KByched
#35 field_multiple_storage-443422-35.patch68.69 KByched
#30 field_multiple_storage-443422-30.patch68 KByched
#28 field_multiple_storage-443422-27.patch67.99 KByched
#26 field_multiple_storage-443422-26.patch67.74 KByched
#25 field_multiple_storage-443422-25.patch65.27 KByched
#22 field_multiple_storage-443422-22.patch65.54 KByched
#20 field_multiple_storage-443422-20.patch80.08 KByched
#18 field_multiple_storage-443422-18.patch80.02 KByched
#15 field_multiple_storage-443422-11.patch52.97 KByched
#10 field_multiple_storage-443422-10.patch25.86 KByched
#8 field_multiple_storage.patch25.81 KByched
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

yched’s picture

Also, support for read-only backends implies :
- hook_storage_info()
- fields (instances) without widgets,
- ... ?

yched’s picture

Title: Make 'storage engine' architecture actually usable » Move away from 'per site' field storage engine

Better title.

bjaspan’s picture

I'm not going to think about this very much right now except to say something that's been on my mind for a while: We should not feel absolutely constrained by the current incarnation of Views. It does not HAVE to work the way it currently works (note that I may not actually know the way it currently works, I haven't looked inside Views 2 yet). Ultimately, if data is going to be stored in multiple locations, it is not going to be queryable and joinable via any single interface. A system that wants to make that possible is going to have to query multiple data sources and do the joins itself.

yched’s picture

We should not feel absolutely constrained by the current incarnation of Views. It does not HAVE to work the way it currently works

True, but we do have serious hints that it will not let you filter/sort on different data sources, because of the theoretical implications. At least, that's how I understand Crell's followup in http://www.palantir.net/blog/remote-data-drupal-museums-and-web-2009#com...
"Searching across separate datasets has no solution that anyone has found that does not involve first caching everything in an intermediary server and then searching that. We're not going to solve that in Fields API in D7" [and I'd add: most likely not in Views D7 either, if Views D7 needs to run on your average shared hosting plan].

But even if Views D7 brilliantly finds a way no one thought of earlier, and lets you do this kind of cool stuff, it will very likely need this information anyway:
- what is the storage backend for each field ?
- what is the primary storage for each Views-enabled entity.
Option 2) above is *just* about making this information available, so I don't think we need to know much more about what views will allow and how, before we can start to move away from 'per site' storage backend.

Obviously, I'd very much like Crell and merlinofchaos to at least subscribe to the issue ;-)

merlinofchaos’s picture

When talking fields, which is purely for display, the storage location is less important. We have pre_render() or some other method of fetching additional data and merging it all together once we have the primary keys. This is easy and we know what we do now works and that can be expanded as needed.

Much like the crappy format that dates are stored in for profile.module, however, sorts and filters are a totally different story. If the data is in 2 discrete locations that cannot be retrieved in a single query, then you have no choice but to retrieve *Everything* and filter locally. So that is frankly never going to happen.

Now, marking fields as belonging to a particular storage engine is, IMO, precisely the way to go. The way Views 3 is looking to work, that is exactly how it will work for Solr, FlickrAPI and whatever other crazy things people come up with with alternate backends.

yched’s picture

Clarified on IRC, merlinofchaos meant "marking fields *and entities* as belonging to a particular storage engine is, IMO, precisely the way to go".

Scott Reynolds’s picture

As the Solr Views maintainer im subscribing to this discussion. I too have had lengthy discussions along these lines. Can't filter/sort anything thats not in the Solr index.

Sounds like there won't be any magik bullet.

yched’s picture

Status: Active » Needs review
FileSize
25.81 KB

OK, first stab at 'per field' storage backend.

- introduces hook_field_storage_info(), to let modules expose their storage types - quite similar to field or widget type info.
- introduces corresponding helper _field_info_*() functions.
- introduces $field['storage'] = array('type' => 'storage_backends', 'settings' => array(...));, and modifies field_create_field() so that it adds $field['storage']['type'] = 'field_storage_sql' if not specified.
- invokes all storage modules on object operations : field_attach_[load|insert|update|delete|delete_revision]().
It's the responsibility of storage modules to only act on fields they actually store. Thus, if several fields in the object are stored by the same storage backend, the module can 'group' queries' if it wants / needs.
- updates field_storage_sql.module accordingly.
- while I was in there, I removed hook_field_storage_[create|rename]_bundle(), they are no different than hook_field_attach_[create|rename]_bundle().

Most probably not perfect, + will need additional tests for "load|edit|delete object using different fields from different backends" (which means an another test backend, yummy - will probably be variable_[get|set]() based, shouldn't be too hard...).

Posting this to see where we stand in terms of test failures...

Status: Needs review » Needs work

The last submitted patch failed testing.

yched’s picture

Status: Needs work » Needs review
FileSize
25.86 KB

Two exceptions, not so bad :-). Updated patch should fix these.

Still TODO:
- a couple PHPdocs
- add a dummy test storage engine and test that an entity can be loaded / saved with fields using different storages.
- handle the case of 'storage module disabled' (this is another case of 'field inactive', there is no working around 'no storage available')

yched’s picture

Status: Needs review » Needs work

Tests green, cool, back to CNW.

bjaspan’s picture

So when I'm adding a field to a fieldable entity type, do I choose the storage backend like I choose the widget, from a list of storage choices that support that field type?

The idea behind the "f_a_pre" hooks is that any module can choose to store (or load, or query/filter/sort) any field data based on any criteria it chooses, and then the default storage engine picks up anything that is left. I realized a while ago that the pre-hooks are really part of the storage API, not the attach API. Also, the pre-hooks are kind of awkard, so rotating them into a better API is a fine idea.

But I wonder about tying a particular field to a field storage backend as a field property. How would pbs.module work, in which enabling a new module changes the way some existing fields are stored?

yched’s picture

So when I'm adding a field to a fieldable entity type, do I choose the storage backend like I choose the widget, from a list of storage choices that support that field type?

Yes, that's the idea. Except storage engine is set at field creation time and cannot be changed afterwards (that is, not without the mythical 'migration' contrib module). And storage engines are not limited to a list of field types they support.

The idea behind the "f_a_pre" hooks is that any module can choose to store (or load, or query/filter/sort) any field data based on any criteria it chooses, and then the default storage engine picks up anything that is left. I realized a while ago that the pre-hooks are really part of the storage API, not the attach API. Also, the pre-hooks are kind of awkard, so rotating them into a better API is a fine idea.

But I wonder about tying a particular field to a field storage backend as a field property.

Hm. Complex area.

I don't think I really envisioned the f_a_pre_* hooks as a way to implement storage backends so far, rather 'optimize per-field-table local storage' (pbs) or 'let $node->status be a field while living in the {node} table'. To me those were two layers addressing slightly different needs.

To me one of the key features in 'abstracted storage handling in Field API' has always been "this specific field lives in a foreign, non-local data repository". The discussion above showed the need for "this field lives in the same foreign location that the foreign_object entity type and can Views can use it in filters and sorts on foreign_object listings".

I've always assumed this was more natural on a field-by-field basis, where each field specifies where it wants to be stored. Mentally trying to reconsider since, true, a large part of the 'storage backend' job can be done through f_a_pre_* hooks.

To summarize:
1) current situation: there's only one actual 'storage backend' active for all the site's fields (usually field_sql_storage.module). 3rd party modules can hook in and bypass it behind the scenes to serve and write field values from/to different locations, according to their own internal logic. Alternate ('remote') field storage use those hooks, and thus not 'storage backends' modules (unless they have a vocation to store node bodies, file uploads, etc..., which is doubtful).
2) direction taken in this patch: several storage backends are active at the same time. Each field explicitly specifies in $field['storage'] which one it uses; if none specified, the site's 'default backend' (usually field_sql_storage.module) is used. 3rd party modules can still hook in and tweak (or do messy things) like previously, but field API 'knows' where a field is supposed to live.

Trying to think of what this means :

- field creation workflow with 1) is
a) field_create_field($field). The 'one and only' active storage module creates the corresponding tables.
b) Inform the 'f_a_pre_* hook'-module that this field_id is in the list of fields it should intercept. Meaning each 'alternate storage' module need to provide it's own way of doing this - a UI or some variable-based settings, probably. There's no guaranty that those settings won't change, or be added later, or get out of sync, meaning a field suddenly changes it's storage location (which we're not supposed to support; means existing data is lost and stays stale).
With 2) this is just:
$field['storage']['type'] = 'my_remote_backend'; field_create_field($field);

- Several 'f_a_pre_* hook'-module can coexist, each one deciding to 'act' (bypass, mirror...) or not on the storage of a given field according to its own logic that only lies in its code. In case of 'bypass' (which is what an 'remote storage' would do), which one wins is a matter of hook execution order. I'm afraid this could get messy.

- While the (contrib or custom) 'f_a_pre_* hook'-module is disabled (think major core upgrade), the field switches back to field_sql_storage. There's a large window for bad things to happen until it's re-enabled. With 2), the field becomes 'inactive' (like when the field type itself is unavailable), and stays out of the way.

- With 1), the Views integration for field_sql_storage.module exposes the field as stored in a regular, local table, thus available for a 'sort' of 'filter by' on local entities (nodes, comments...). The 'f_a_pre_* hook'-module should hook_views_data_alter() those entries out, in addition to providing its own views integration. Possibly no big deal, I'm not 100% sure.

- Also, I expect some of those 'foreign repositories' to be read-only. With 2), storage 'descriptors' in hook_field_storage_info() + $field['storage']['type'] make it easy to do 'if storage module is read-only, don't show the field's widget in edit forms' in field_default_form(). Not doable with 1) since the black magic happens behind the scenes inside hook_f_a_pre_*().

- More generally, with 1), we never know where a field is actually stored and how this storage behaves; we just invoke the hooks and let them do their stuff. I suspect that could be a problematic limitation in more places than just edit forms.

How would pbs.module work, in which enabling a new module changes the way some existing fields are stored?

Well, to me the scope of pbs is to provide an alternate storage structure for fields stored by the regular field_sql_storage ? Or at least, fields stored in the local db by an alternate 'other_local_sql_contrib_storage_so_much_more_clever_than_cores_sucky_default_storage' module ?
Then it would act only if ($field['storage']['type'] = 'field_sql_storage') - or, $storage = field_info_storage_type($field['storage']['type']); if ($storage['location'] == 'local_db')

Again, this is a complex area and I'm not claiming I have the answers :-/. As the above shows, I'm currently biased on approach 2), though...

yched’s picture

Thought of that one later:
If I want to implement an alternate storage backend,, I'm basically writing an "equivalent" of field_sql_storage.moule, and it's that module I'll naturally study and adapt. Thus, rather hook_field_storage_*() than f_a_pre_*().

yched’s picture

Title: Move away from 'per site' field storage engine » 'per field' storage engine
Status: Needs work » Needs review
FileSize
52.97 KB

Updated patch:
- completes the docs
- implements a dummy but full-fledged test storage backend using the {variables} table. Fun.
- tests saving / loading an object with fields using different storage backends

still TODO
- handle the case of 'storage module disabled' (this is another case of 'field inactive', there is no working around 'no storage available')

Status: Needs review » Needs work

The last submitted patch failed testing.

chx’s picture

Priority: Normal » Critical
yched’s picture

Status: Needs work » Needs review
FileSize
80.02 KB

- Fixes the exceptions in #15,
- adds handling of 'storage module disabled'
- adds a test for the 'inactive field' behavior on module enable / disable.

Let's see what the bot says, tests are a *pain* to run on my setup tonight.

The last submitted patch failed testing.

yched’s picture

Fixes the tests for 'active / inactive field'

chx’s picture

+// function testFieldAttachCache() { ?

yched’s picture

Indeed. Always my recurring habit of commenting some tests out to run the one I want quicker, and then forgetting to uncomment before rolling the patch.

chx’s picture

Some real feedback. This is weird to say the least:

    foreach (module_implements('field_storage_load') as $module) {
      $function = $module . '_field_storage_load';
      $function($obj_type, $queried_objects, $age, $skip_fields, $options);
    }

If I read this code correctly this is not per field storage but "come everyone do you have something stored for this field"? I thought we will have a storage engine key in the field definition?

yched’s picture

Yes, it's the responsability of the storage module to act only on fields using the storage backend it implements.
See field_test_field_storage_load(), or

-      if (!isset($skip_fields[$field_name]) && (!isset($options['field_name']) || $options['field_name'] == $instance['field_name'])) {
+      $field = field_info_field($field_name);
+      if ($field['storage']['type'] == 'field_sql_storage' && !isset($skip_fields[$field_name]) && (!isset($options['field_name']) || $options['field_name'] == $instance['field_name'])) {

in field_sql_storage_field_storage_load().

yched’s picture

yched’s picture

Attempt to simplify the code pointed in #23-#24. That logic is now moved to the caller (field_attach_load()), hook_field_storage_load() receives a list of $fields it should load, period.
Just converted _load for now, letting the bot run.

Status: Needs review » Needs work

The last submitted patch failed testing.

yched’s picture

Status: Needs work » Needs review
FileSize
67.99 KB

Oops, that one should be better.

Status: Needs review » Needs work

The last submitted patch failed testing.

yched’s picture

Status: Needs work » Needs review
FileSize
68 KB

silly typo.

Status: Needs review » Needs work

The last submitted patch failed testing.

bjaspan’s picture

I'm pondering this. I agree with all the most/all of the reasons in #13 that the f_a_pre_* hooks are not a good API, but something about the new approach does not seem quite right to me yet.

yched’s picture

OK, I'll wait a bit before rerolling, then ;-)

yched’s picture

Just a note that I'll try to move forward on this by the end of the week.

yched’s picture

Status: Needs work » Needs review
FileSize
68.69 KB

Painful reroll after 'Bulk delete', no changes, just checking tests.

Status: Needs review » Needs work

The last submitted patch failed testing.

yched’s picture

Status: Needs work » Needs review
FileSize
68.1 KB

Incorrect reroll indeed. field_name / field_id snafu. An error on field load doesn't go unnoticed :-p
Let's see with this one.

yched’s picture

Hm, I moved forward on the conversion of field_storage hooks started in #26, but the commit of #367595: Translatable fields will make for another reroll fest.
Well, glad that the post-'Bulk delete' reroll at least returned green for a short period of time :-/

Status: Needs review » Needs work

The last submitted patch failed testing.

yched’s picture

Status: Needs work » Needs review
FileSize
74.51 KB

Painful reroll after the Translatable field patch.
Not finished yet, just checking how bad tests are.

Status: Needs review » Needs work

The last submitted patch failed testing.

yched’s picture

Status: Needs work » Needs review
FileSize
74.47 KB

heh, reapplying a patch rolled in the drupal_function_exists()-era is bound to cause a few surprises...
Let's try again.

Status: Needs review » Needs work

The last submitted patch failed testing.

yched’s picture

Status: Needs work » Needs review
FileSize
68.29 KB

Better. How about this one ?

Status: Needs review » Needs work

The last submitted patch failed testing.

yched’s picture

Status: Needs work » Needs review
FileSize
70.09 KB

And this one ?

Status: Needs review » Needs work

The last submitted patch failed testing.

yched’s picture

Status: Needs work » Needs review
FileSize
72.14 KB

That one should leave only 'bulk delete' failures. That's it for tonight.

Status: Needs review » Needs work

The last submitted patch failed testing.

bjaspan’s picture

I think I approve of the general direction here now.

What is concerning me is the notion that fields have "a" storage location, because we know that they may have multiple locations, e.g. from pbs.module or field_parallel_memcache_storage.module (the latter might store a copy of all field data in multiple memcache servers so all they fields can be read back in parallel later). It looks like you've preserved the "pre" hooks so these modules are still possible to implement, but there is no way for them to say that they are mirroring the data. This I think is why I was leaning towards a hook for "where is this field stored?" instead of declaring that info in $field['storage']: the former makes it easy for multiple modules to stay "it is stored here." But Field API does not have that capability now, anyway, and it would make things more complex.

The "pre" hooks probably belong in the field_storage namespace, not the field_attach namespace.

yched’s picture

New patch should fix remaining failures. Patch is not finished yet, but at least we're through with the 'translatable fields / bulk delete' reroll hell.

Still TODO:
- update the 'test storage engine' and make sure it passes all tests (I'll probably let the bot run in a dummy issue to not add more clutter to this one)
- update PHPdocs
- figure out a WTF around translatable fields in field_sql_storage_field_storage_write()
- write a summary :-/

yched’s picture

re bjaspan #50:
Agreed that fields having separate storage locations makes #569224: Expose field storage details through field attach. a little trickier, but I don't think the patch changes anything on that regard. In current HEAD's 'one single storage backend for all fields' approach, PBS or field_parallel_memcache_storage.module already imply primary + secondary storages and the need for 'exposed storage info' to account for that. This patch only makes it so that the primary storage is not necessarily the same for all fields on the site.

The "pre" hooks probably belong in the field_storage namespace, not the field_attach namespace.

100% agreed, we've been postponing that for a while. Do we want to to the change in this patch, though ?

yched’s picture

Status: Needs work » Needs review

forgot to set to CNR

Status: Needs review » Needs work

The last submitted patch failed testing.

yched’s picture

Status: Needs work » Needs review
FileSize
74.19 KB

Status: Needs review » Needs work

The last submitted patch failed testing.

yched’s picture

Status: Needs work » Needs review
FileSize
74.25 KB

Should be better. Also updated field_test_storage, but I still need to validate its tests.

yched’s picture

Reroll after #569072: Clean field_attach_* namespace and #569240: Remove field ID from field table names.

+ Behind the scenes, making progress on having the test_storage backend pass all tests.

yched’s picture

Status: Needs work » Needs review
FileSize
80.5 KB
80.5 KB

I'm done with the remaining TODOs, patch should be ready for human review now.

Summary of what the patch does :

- Promotes 'storage backend' as a pluggable field property, quite like field types, widgets or formatters
--> introduces hook_field_storage_info(), hook_field_storage_info_alter(), field_info_storage_types(), field_info_storage_settings()
--> {field_config}.storage_type
--> new section in the $field definition array():

$field['storage'] = array(
  'type' => the name of the storage backend
  'settings' => settings for the storage backend (not sure about actual use cases, 
                but this stays consistent with what we have for field types, widgets and formatters)
);

The storage backend should be specified in field_create_field($field). By default, we use the backend specified by the 'field_storage_default' variable. We don't support changing storage backend on existing types (that's a job for contrib)

- Marks fields as 'inactive' when their storage module is disabled (like what we currently do when the field type module is disabled).
--> {field_config}.storage_module, {field_config}.storage_active, field_modules_disabled(), field_associate_fields()
Adds a test for this.
--> FieldCrudTestCase::testActive()

- The patch currently does not add any UI. All custom fields created through field_ui use the default storage backend. I'm not sure we'll want to change that. Using different storage backends is a rather advanced task.

- All hook_field_storage_[load|write|delete|...]() functions receive a $fields parameter, listing the fields they should act on. This notably lets us move some tricky logic out of the hooks and into the caller field_attach_* functions.

- Removes hook_field_storage_[create|rename]_bundle(), storage backends can use the existing hook_field_attach_[create|rename]_bundle() 'generic' hooks. Note that this was already the case for _delete_bundle().

- Fixes a snafu around multilingual fields in field_sql_storage's hook_field_storage_write() ($object->name = empty array did not wipe existing data - added a test for that), and streamlines this code a little.

- Adds a dummy but full-fledged 'field_test_storage' backend in field_test.module (stores field values in the {variable} table)

- Adds a test to check we correctly save and load an object with two fields using different backends.
--> FieldAttachStorageTestCase::testFieldAttachSaveLoadDifferentStorage()

- Sets the bases for reusing field tests across different storage engines. Coding the dummy 'field_test_storage' backend showed that writing an alternate storage backend without a full test suite to validate upon is fairly hard.
--> $default_storage property on the FieldTestCase parent class.

In a followup patch, we should have field.test run against the 'field_test_storage' backend, and have field_sql_storage.test take care of running them with field_sql_storage.
Would IMO add too much cruft in this patch. For now I just upload two versions of the patch (one line change), to check that both 'field_test_storage' and 'field_sql_storage' backends pass all our tests. Only field_multiple_storage-443422-60.patch is a candidate for inclusion.

Status: Needs review » Needs work

The last submitted patch failed testing.

yched’s picture

plach’s picture

subscribe

profix898’s picture

subscribing

yched’s picture

bump :-)

I think this is ready, but we need some reviews so that it can reach RTBC in time...

bjaspan’s picture

This is awesome. I have a few trivial comments:

* Debugging code in "Check that the storage type is known."
* Redundant unset() after "// not have its own column"
* "An array listing the fields to be written. The keys and values of the array are field ids." Why not have the values be the field structure instead of the ids?

My hope is to fix these problems, make pbs.module work with that patch, and absorb the wisdom behind the decision not to pass field structures as values to field_storage hooks, then mark this RTBC. Hopefully I'll even get to it tonight, since I do NOT want this patch to need re-roll...

bjaspan’s picture

Status: Needs review » Reviewed & tested by the community
FileSize
86.41 KB

I fixed the debugging code and redundant unset() from #65. I did not change the $fields arg to field_storage hooks to have field structures as values. I actually do not see why they aren't/can't be field structures, but that is an easy fix for a followup patch, and is not critical.

I found (or, rather, the per-bundle storage tests found) one actual bug: field_read_instances() was not adding a condition on the new field_config column fc.storage_active when querying for instances whose fields are in fact active. Very simple fix.

RTBC, and yched earns a gold star.

mattyoung’s picture

sub

Status: Reviewed & tested by the community » Needs work

The last submitted patch failed testing.

bjaspan’s picture

Status: Needs work » Reviewed & tested by the community
FileSize
86.48 KB

Re-roll.

Status: Reviewed & tested by the community » Needs work

The last submitted patch failed testing.

bjaspan’s picture

Trying to fix the PHP syntax error in #69 revealed a mistake in this patch. All the field_storage hooks are invoked like this:

    module_invoke($storage_type['module'], 'field_storage_create_field', $field);

This is wrong, because the function name is based on the field storage *module*, not the field storage *type*. All our other info hooks allow a single multiple to define multiple (field,widget,formatter) types. Storage info is clearly intended to work the same way. This will be easy to fix by changing the code above to something like

    module_invoke($storage_type['type'], 'field_storage_create_field', $field);

but it will need to be done and documented before this patch is CNR again. I'll try to do this today.

yched’s picture

re #66 : "I did not change the $fields arg to field_storage hooks to have field structures as values. I actually do not see why they aren't/can't be field structures, but that is an easy fix for a followup patch, and is not critical."

I think I went back and forth on this. The thing is the 'load' hook uses $fields as an array mapping field ids to the ids of the objects to load for each field. The logic to collect this info is a bit tedious so it's more precious to provide the 'load' hook with that rather than the field structures, that are easy to access with the id. For the other (non 'load') hooks, I just stayed consistent. I guess they could receive the $field_id => $field array instead of the redundant $field_id => $field_id array. Building and passing that array has a slightly higher memory cost, but would save a few field_info_field_by_id() calls.

re #71: That's how the hooks currently work for field type / widget hooks : [module]_field_load() or [module]_field_widget() are called by module, not by field type or widget type. If a module implememts several field types or widgets, those hooks are likely based on a switch. That's one of the worst things in our current architecture, that we didn't bother / dare change from CCK : we handle as 'hooks' what are in fact callbacks (or methods in a OO design) :-(

yched’s picture

And thanks for bringing this home, Barry :-)

bjaspan’s picture

Status: Needs work » Reviewed & tested by the community
FileSize
87.98 KB

Re-roll for #569364: Handle failures on field storage creation. The test for field storage failure involved field_test_field_storage_create(), and this patch added a different version of that function. field_test.module now defines two field storage engines, one of which always fails. So, nothing changed except updating the tests. Still RTBC.

bjaspan’s picture

Re-roll now that field_update_field() is committed. The only change is that to this patch is that field_update_field() now always refuses to update a field's storage type.

Dries’s picture

Status: Reviewed & tested by the community » Needs work

I reviewed this patch along with two cups of coffee, and committed to CVS HEAD. It's a great patch, and one of the principal reasons why we decided to rewrite large parts of CCK to begin with.

Instead of marking this 'fixed', I'm going to set this 'needs work' because I think it would be good to add some extra code comments to the new code in 'field_test.module' and because not all new hooks are documented in the API documentation. So, let's follow-up with extra goodies to polish this up.

Thanks for the amazing work @yched and @bjaspan. Nice!

plach’s picture

Crossposting an issue introduced by this one: #590590: field_create_field ignores the 'translatable' property.

litwol’s picture

Issue tags: +Needs documentation

Tagging appropriately

catch’s picture

Priority: Critical » Normal
vanillawater’s picture

Status: Needs work » Needs review
Issue tags: -Needs documentation

#8: field_multiple_storage.patch queued for re-testing.

retester2010’s picture

Status: Needs review » Needs work

The last submitted patch, field-multiple-storage-443422-75.patch, failed testing.

fgm’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, field-multiple-storage-443422-75.patch, failed testing.

colan’s picture

cilefen’s picture

@colan Should this be closed as a duplicate and the other issue back-ported?

colan’s picture

@cilefen: This one is effectively done. It was left open to add documentation. So, assuming that's not actually going to get added, we should mark this as fixed, not as a duplicate.

If you want the other issue backported to D7, you should use that other issue, and set the status to "Patch (to be ported)", and then update the Version (to D7). But I wouldn't bother at this point (unless you plan on working on it yourself) as it's unlikely someone will spend any resources on that this late in the D7 game.

  • Dries committed 803b8b3 on 8.3.x
    - Patch #443422 by yched, bjaspan | chx, merlinofchaos, Scott Reynolds,...

  • Dries committed 803b8b3 on 8.3.x
    - Patch #443422 by yched, bjaspan | chx, merlinofchaos, Scott Reynolds,...

  • Dries committed 803b8b3 on 8.4.x
    - Patch #443422 by yched, bjaspan | chx, merlinofchaos, Scott Reynolds,...

  • Dries committed 803b8b3 on 8.4.x
    - Patch #443422 by yched, bjaspan | chx, merlinofchaos, Scott Reynolds,...

  • Dries committed 803b8b3 on 9.1.x
    - Patch #443422 by yched, bjaspan | chx, merlinofchaos, Scott Reynolds,...
bradjones1’s picture

Version: 7.x-dev » 8.0.x-dev
Status: Needs work » Fixed

Status cleanup; this was long-since-committed and the version is misleading; there could be a backport, but per #87 that should happen on a separate issue.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.