(For details on this, visit http://groups.drupal.org/node/12838 and possibly also the links there.)

Wanting to present search results of the Apache Solr search engine with Views, I encountered the problem that Views is fixed on obtaining its data from the database.
The attached patch allows for the definition of a different, arbitrary back-end for base tables. All one has got to do in order to achieve this is create a new query class that at minimum needs to define a query() and (although this may change) a get_where_args() method and set $data[$base_table_name]['table']['base']['query class'] to the name of this class in hook_views_data().

At the moment it is not a really elegant solution, but it should at least work. Any suggestions to improve the whole thing are welcome.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

drunken monkey’s picture

Status: Active » Needs review
FileSize
9.93 KB

Sorry, just now realized the patch didn't get attached. Hope it's there this time.

drunken monkey’s picture

Updated patch attached. It now applies to the latest version and I also changed the design of the view_query->execute() method to directly set the view object fields, instead of returning an array. While this is against good OOP practice, I think in this case it makes the code a lot cleaner.

fago’s picture

Status: Needs review » Needs work

the call
$this->query->get_where_args();
isn't needed any more in build().

Why do you remove the initial assignment?
$this->query = new stdClass();

I think this is is a mistake:
- // This reference deals with difficult PHP indirection.
+ // This reference deals with difficult PHP indirection.6/10/2008

in views_object_types, why do you remove - // statically cache this so t() doesn't run a bajillion times. ?

Then I tried this on my test site and now no (usual db) view returns any results. :(

fago’s picture

Category: feature » task
Status: Needs work » Needs review
FileSize
8.54 KB

hm, I tried it again and I couldn't reproduce the mentioned problem on my test site. So probably it was a problem of my installation - sry for that.

I've edited and cleaned up the patch from stuff I think it's unneeded - as mentioned above. Furthermore I changed get_where_args() to actually return something - imho otherwise this is confusing. Furthermore your patch killed the live preview previously - the $view->build_info is actually needed. I've fixed that.

attached, is an updated patch. My views installation seems to keep working fine with it - drunkenmonkey, could you test it with your solr backend too pls?

Then I've seen that you restrict hook_views_query_alter to the views_query class only - is there a cause for that? Does it break something if we do not? Imho it should be possible to alter queries from other backends too.

drunken monkey’s picture

Status: Needs review » Reviewed & tested by the community

Thanks for testing again and for your work!
With your patch, everything seems to work fine here.

Then I've seen that you restrict hook_views_query_alter to the views_query class only - is there a cause for that? Does it break something if we do not? Imho it should be possible to alter queries from other backends too.

It should be able, you are right. The problem, however, is, that the modules implementing the hook expect the first argument to be an instance of views_query. If it isn't, this could result in a call to an non-existing function and, hence, in a fatal error.
So as long as implementations of the hook are not aware of the different classes, we cannot pass them objects from classes other than views_query.

aufumy’s picture

FileSize
8.97 KB

Re-rolled patch with latest views from cvs HEAD

drunken monkey’s picture

What's the status of this, apart from RTBC? Will it ever be committed?
If not, what are the issues?

The patch took me (and probably fago, too) quite a while and I would like at least to get feedback, why it isn't included.

aufumy’s picture

This may not be very helpful, but when I installed the module, and added the apachesolr argument or filter, it did not return the results I was expecting. However, I was in a rush so did not have too much time to try to figure out what was going on, etc.

I'll give it another spin, and give a better report.

Thanks
Audrey

merlinofchaos’s picture

The commit status is that I'm requesting that this patch be maintained but I will probably commit it when I branch for Views 3. Note that Views 3 is not as drastic of a departure as Views 2 was, so don't think of it is quite as big of a jump. But once this goes in some things, at least in my mind, will be significantly different and I do not want to endanger the 2.x line with it.

That said, I do want this, but we are biding time with it.

fago’s picture

hm, I think maintenance shouldn't be the problem. However time might be.. I fear that views 3 is too far away for my needs :(

langworthy’s picture

I'm getting failure notices when patching. Does this mean it needs to be re-rolled?

jmiccolis’s picture

FileSize
8.88 KB

I've rerolled the patch against head. It looks like the switch from microtime to views_microtime is what changed in views and caused the failure reported above.

Can't wait to see this get committed.

merlinofchaos’s picture

Ok, I have only one complaint about this patch:

+ if ($query_class == 'views_query')

Let's avoid this. Call through to the query class and let it decide what to do. That way other query classes can use their version of query alter or whatever.

Otherwise, this is less intrusive than I thought it woudl be and I can get this in after all.

drewish’s picture

Status: Reviewed & tested by the community » Needs work

i'm going to be super nitpicky since i doubt it'll stop earl from committing it if he's into it ;)

yeah the query class testing seems like a bad smell. the SQL signature injection should probably become an option on the query builder.

if we endup going with

+    // Only do this, if the default query class is used.
+    if ($query_class == 'views_query') {

it should include a big TODO to relax the restriction in later versions of the API. or maybe we could ask the class if it's alterable?

i'd sort of like to see $external given a default value at the top of the function with a comment on it's purpose. I'd also like a little whitespace before

+      if (!empty($external)) {
+        db_set_active();
+      }

so it doesn't get lost in the previous block of code.

while we're in here can we make these comments into proper sentences?

+          // dump information about what we already know into the globals
+          global $pager_page_array, $pager_total, $pager_total_items;
+          // total rows in query
+          $pager_total_items[$view->pager['element']] = $view->total_rows;
+          // total pages
+          $pager_total[$view->pager['element']] = ceil($pager_total_items[$view->pager['element']] / $view->pager['items_per_page']);
jmiccolis’s picture

FileSize
9.1 KB

The attached patch should address the issues raised above. I've moved the invocation of hook_views_query_alter into the query class, given $external a default value (with an explanatory comment), and made the pager comments into sentences.

jmiccolis’s picture

Status: Needs work » Needs review

Setting status to 'needs review'.

Ian Ward’s picture

I tested this patch, it applied fine. I was also able to build a normal view w/ nodes, as well as a view using an external source w/ a test module.

merlinofchaos’s picture

Ok, this could probably go in as is, but I'm a little concerned with the organization of what we're doing here. If we extend to a time down there road when there is a query object for solr, sparql, flickr, delicious, twitter and some other esoteric thing where we're doing odd integration, there is absolutely no organization to the query objects.

The query class should probably be registered similar to handlers, and with a pointer (auto-generated, most likely) to the file that the query object is in. That way the query object won't have to be loaded if it's never used. The existing query class possibly even needs to be renamed to views_query_sql or something to specify which kind of query it is.

I guess we don't need a base query class, since the only truly required interface on the query class is execute() and alter() -- everything else is fairly specific to the class.

Now, these things may not be necessary right away. Renaming the query class is a bit of an undertaking. Registration, however, is pretty easy. We can even register it as a plugin so we don't need a separate hook or anything. And registration would allow some fairly nifty stuff with subclassing and allowing modules to actually replace the query object for existing things with something else.

I'm not going to set this CNW, though until I've thought about this some more.

dragonwize’s picture

Very interesting stuff. For those interested Jeff from Development Seed used this patch to create a proof of concept for Flickr API. http://www.developmentseed.org/blog/2009/feb/05/extendr-flickr-and-views

fago’s picture

I'm really excited about the progress here! :))

But of course we need to make sure to get it done right. Registration as plugin sounds to be really useful and straight forward. More thoughts on this, merlin?

merlinofchaos’s picture

hook_views_plugins already registers multiple plugin types, so 'query' could be its own type.

We would then need 'views_plugin_query' as a base type which describes the basic operations (->execute() and ->alter() I think) and all query plugins would then be registered that way. Otherwise everything else looks pretty similar to this patch, I think.

jmiccolis’s picture

Assigned: Unassigned » jmiccolis
Status: Needs review » Needs work

Great, I should be able to dedicate a some time tomorrow to this.

jmiccolis’s picture

Assigned: jmiccolis » Unassigned
Status: Needs work » Needs review
FileSize
75.94 KB

Attached is patch that makes the query object into a plugin. I'm providing a interface-like base query class "views_plugin_query", which extends "views_plugin". The default query building functionality has been moved form "query.inc" and into "views_plugin_query_default.inc".

Two unexpected things came up to take note of:

  1. By extending "views_plugin" I grow the capabilities/size of the standard query class. Some of what is in "views_plugin" is needed based on how plugins get loaded, but it's not going to be used in actual query construction, though it may prove useful in adding options to query classes later on.
  2. The interface implied in "views_plugin_query" is not really complete. Methods like "add_field" get called by simple handlers like "views_hander_field". This means that when you provide a new query object you'll need to either provide a complete set of custom handlers, or implement the more extensive interface that "views_plugin_query_default" does.
drunken monkey’s picture

The patch looks good to me. I tested it and all normal views (including creating, ..., them) seemed to work fine. I just couldn't bring a view with a new query class to work, but this is probably rather my fault than the patch's. I'll keep on trying it.

One more thing, regarding the inelegant class test, that Earl critisized. Maybe we should change this:

    if (variable_get('views_sql_signature', FALSE) && $query_class == 'views_query') {
      $this->query->add_field(NULL, "'" . $this->name . ':' . $this->current_display . "'", 'view_name');
    }

to something along these lines:

    if (variable_get('views_sql_signature', FALSE)) {
      $this->query->add_signature();
    }

Once this is committed and modules start implementing their own backends, this would be very difficult to do.
Another option would be to pass a $add_signature argument (or even a $options array argument, which could be very useful for later extensions) to the query() method.

jmiccolis’s picture

Thanks for the review! I also agree that the class test could still be better. I'll wait for Earl to weight in about moving the signature - perhaps we should let the query class handle it entirely and not have any of this logic in view.inc.

As far as getting this working with a new query class take a look at my flickr implementation which may be helpful.

drunken monkey’s picture

Status: Needs review » Reviewed & tested by the community

It really was very helpful, thanks!
Since your module requires a Flickr API Key, I couldn't test the patch with this query class, but I finally managed to bring my own to work.
So afaict the patch is OK, only the little issue above seems to remain. Good work, anyways!

drunken monkey’s picture

Status: Reviewed & tested by the community » Needs work

Oh, no, too hasty. I just discovered that if the query class hasn't got the method get_where_args(), it results in the following error:

Fatal error: Call to undefined method apachesolr_views_query::get_where_args() in .../views/includes/view.inc on line 628

Either this should be fixed and the logic in the corresponding views-method moved to the query class (the way I'd prefer it), or views_plugin_query should have the get_where_args() explicitly. I'll try to look into it tomorrow.
I think, all other methods not in views_plugin_query can really be omitted, so it's just the one.

drunken monkey’s picture

Regarding the issue mentioned above, I've got two approaches:

1) Introduce a new method, views_plugin_query->build_info() which gets called between alter() and execute() and takes care of filling the build_info with the last pieces of necessary information. I.e., in views_plugin_query_default it would look like this:

function alter(&$view) {
  $view->build_info['query'] = $this->query();
  $view->build_info['count_query'] = $this->query(TRUE);
  $view->build_info['query_args'] = $this->get_where_args();
}

2) Since in the above solution, making query() explicitly part of the interface is unecessary, the alternative would be to just change the definition of query() so it directly fills $view->build_info with the necessary information/queries. views_plugin_query_default->query() would then look like this:

function query(&$view) {
  $view->build_info['query'] = $this->_query();
  $view->build_info['count_query'] = $this->_query(TRUE);
  $view->build_info['query_args'] = $this->get_where_args();
}

With the original query() method renamed to "_query()".

Personally, I'd prefer the second variant, since imo it looks cleaner.
Two patches with speaking names are attached.

jmiccolis’s picture

Status: Needs review » Needs work
FileSize
76.11 KB

Good catch - get_where_args() is certainly needed. I'd like to suggest a third alternative. Instead changing the internal workflow of view::build() we could just add a stub-ish get_where_args() metod to the views_plugin_query class.

Patch is attached.

drunken monkey’s picture

OK, this would probably be the easiest solution, you're right.
But since the method doesn't make much sense for most types of query class, I'm a bit worried about putting this in the base class, even as a dummy implementation, in terms of good style and clearness of the interface.

Well, good idea anyways. Let's just let Earl decide which approach to take.

fago’s picture

I think the best way to go what be solution 1 from #28. But perhaps just name the method build() roo - so $view->build() would invoke $query->build(), which writes into $view->build_info.

@#29:
"where" is sql specific, so I would take the solution above. Furthermore it allows the query plugin to pass even more stuff to execute() if necessary.

jmiccolis’s picture

@fago, sure - I'm totally fine with using solution 1 from #28. ...also I'm neutral on the method name change, but in the interest of moving this forward...

@drunken monkey - do you want to re-roll that patch with the method name change and set this to 'needs review'?

drunken monkey’s picture

Status: Needs work » Needs review
FileSize
76.48 KB

OK.

drunken monkey’s picture

Sorry, was sloppy, here is the right one.

merlinofchaos’s picture

Status: Needs review » Needs work

Upon attempting to apply the patch in #34 I found *several* cases in views_plugin_query_default::execute() that had not properly turned '$this' into '$view' causing total failures. These need to be cleaned up.

drunken monkey’s picture

Status: Needs work » Needs review
FileSize
76.48 KB

Sorry about that, I didn't notice. A refined patch is attached, with no '$this' at all in that method. So at least this method should be OK, I hope it didn't happen elsewhere too.

What strikes me as odd, though, is that I didn't notice any errors while testing the patch...

fago’s picture

Should we increase the views api version number? See http://drupal.org/node/254565#comment-1276500

But if we would do so, views would only use APIs written for >2.0, so probably that's a bad idea. So probably best modules depending on this feature should check whether the right views version is available and only return their views integration infos, if it's ok? Thoughts?

jmiccolis’s picture

FileSize
76.59 KB

Attached is an updated patch that includes a recent change to query.inc http://cvs.drupal.org/viewvc.py/drupal/contributions/modules/views/inclu... and corrects a typo in #36

fago’s picture

more @API:
>But if we would do so, views would only use APIs written for >2.0, so probably that's a bad idea

We could also bump the API to 2.4 or whatever and change views to accept all 2.0-2.4 APIs. So elder versions of views would just ignore new views integration relying on this patch. What do you think about that merlin?

alex_b’s picture

FileSize
76.39 KB

I just tested this patch with latest views 2.x dev and extendr.

Patch does neither break existing views nor existing default views: I tested 2 default views and 4 views with a before/after comparison of patch applied and caches cleared.

I rerolled to reflect two tiny changes to query.inc in views_plugin_query_default.inc (query.inc 1.40 and 1.41).

This is great work and opens a whole new world of possibilities, I'm hoping we can use this in production soon.

jmiccolis’s picture

Status: Needs review » Reviewed & tested by the community

The patch in #40 looks ready to go to me. Thanks Alex.

moshe weitzman’s picture

Subscribe. migrate module would like to select files in a directory tree. It would be like a UI for file_scan_directory.

sirkitree’s picture

We'll be using in production soon and are starting some testing. Mostly for Solr purposes. Great stuff!

jmiccolis’s picture

@sirkitree just fyi, I spoke to Earl briefly about this patch at Drupalcon DC and it looks like the plan is to commit this after the next point release of views (2.4).

m3avrck’s picture

subscribe -- we're running this now in conjunction with the solr patch: http://drupal.org/node/254565

timcosgrove’s picture

subscribe

merlinofchaos’s picture

2.4 is out. Please reroll this. AS soon as I feel confident I don't need to make an emergency release post 2.4, I'll get this sucker committed.

jmiccolis’s picture

Assigned: Unassigned » jmiccolis

Great. You'll have it mid-day tomorrow.

jmiccolis’s picture

Assigned: jmiccolis » Unassigned
Status: Reviewed & tested by the community » Needs review
FileSize
76.83 KB

Attached is a re-rolled patch, which incorporates the recent changes to query.inc

yhahn’s picture

Status: Needs review » Reviewed & tested by the community

Reviewed and tested by this community of 1:

  • Patches cleanly against CVS checkout (May 14, 2009) and Views 2.5.
  • Works with miccolis's sample module extendr (http://svn3.cvsdude.com/devseed/sandbox/drupal-6/extendr).
  • Successfully built a page view that displays flickr photos with argument handler for flickr username.
  • Existing views work correctly.
Scott Reynolds’s picture

This patch is working great with this module: http://drupal.org/project/apachesolr_views

merlinofchaos’s picture

Status: Reviewed & tested by the community » Fixed

I have branched a 3.x dev branch and made this the first commit. There are other largish things and it seems like this is a good time to start work on Views 3 for real.

Great job, folks, this is a fantastic feature and I'm glad you all stuck it through even though I've been very slow.

catch’s picture

Version: 6.x-2.x-dev » 6.x-3.x-dev

ahem.

Status: Fixed » Closed (fixed)

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

Scott Reynolds’s picture

FileSize
45.16 KB

I have re-rolled this against 2.6. I can't move to 3.0 and I wan the security improvements and the caching of 2.6. I provide it here for those looking.

Scott Reynolds’s picture

FileSize
77.67 KB

m3avrck pointed out the major difference in size of the two patches. This is because i didn't 'remove' the plugins/query.inc. Attached has that file removed.

Scott Reynolds’s picture

FileSize
77.74 KB

And I over-wrote a the query caching... here is the latest re-roll.

pmarreddy’s picture

i was not able to get the patch work against views 2.6.

pmarreddy’s picture

Status: Closed (fixed) » Needs review

i was not able to get the patch work against views 2.6. it is giving couldn't open file \dev\null error (i am using tortoise on windows) once the patch is done the query doesn't have any content it, is there any other patch i have to apply before i apply backend.patch the one in 57 to 2.6. (i am a newbie here, please forgive me for asking)

adv thanks

merlinofchaos’s picture

Status: Needs review » Closed (fixed)

This patch will not be committed to the 2.x branch. It is the *reason* for the 3.x branch. I appreciate that it is here for people who want to run a patched 2.x, though at that point you're really running the 3.x code so I'm not sure what the point is.

dawehner’s picture

Issue tags: +views 3.x roadmap

adding tag to find this later

wonder95’s picture

I've been reading through this thread, and I could really use it, and pardon me if I'm being blind, but I'm not seeing how to implement this with Solr. I've downloaded 6.x-3.x-dev, but I'm not understanding what to do next. I would look at the Flickr Extendr module, but the link to it above doesn't seem to have anything there any more. Can anyone point me in the right direction?

Thanks.

Update: Never mind, I figured it out.

webchick’s picture

FYI: The link to extendr module above is broken. Here's the correct link: http://devseed.svn.cvsdude.com/sandbox/drupal-6/extendr/

nightowl77’s picture

Subscribing

Yorgg’s picture

subscribing

claudiu.cristea’s picture

Status: Closed (fixed) » Active

Where can I find some docs/wikis/tutorials about how to define a custom backend?

dawehner’s picture

Status: Active » Closed (fixed)

In general i suggest you to create new issues for such questions, but i see it can make sense for you.

There are several example places to look:
- apachesolr_views
- twitter_views
- extendr
- mongodb_views in chx sandbox

You need the following basic steps
- write hook_views_plugins and register your query plugin
- write hook_views_data and set your query plugin there
- implement the query plugin.

Cameron Tod’s picture

subscribing

zilverdistel’s picture

I'm very interested in finding documentation about how to write my own views3 backend for a REST-full API we're using.

Can someone point me in the right direction? I downloaded the modules in #67, and am trying to set things up now.

zilverdistel’s picture

I managed to get this working. Should we start some documentation on how to do this (best practices, pitfalls, ...)?

Maybe this should be a new issue? Not sure.

webchick’s picture

Yeah, go ahead and start a new issue, since this one has been closed for some time (you can link to it from this issue tho). Documentation on this would be VERY much appreciated by many! Thanks for stepping up! :D

zilverdistel’s picture

Ok, created a new issue for this on http://drupal.org/node/1071480.

gnindl’s picture

Version: 6.x-3.x-dev » 6.x-2.16
Status: Closed (fixed) » Needs review
FileSize
79.56 KB

Ported patch from #57 to version 2.16. In my case my views heavy theme wasn't compatible with version 3.0. Therefore it was much easier to port a patch than refactoring dozens of templates files.

Anyway, backporting is a feature of any mature software. You shouldn't mind guys taking up the effort :)

If anyone is interested I post a patch here.

Status: Needs review » Needs work
Issue tags: -views 3.x roadmap

The last submitted patch, views_patch_query_plugin-backport-2.16-patched3.patch, failed testing.

MustangGB’s picture

Issue summary: View changes
Status: Needs work » Closed (won't fix)