Views only supports MySQL's two levels of namespacing -- database name, and table name -- whereas the SQL spec requires three levels. In PostgreSQL, for example, these are Database -> Schema -> Table. Postgre and Oracle both use '.' as a delimiter, so for example, you'd use 'people.users' to specify the 'users' table in the 'people' namespace.

This prevents Views being used to access any SQL-compliant database that uses this namespacing.

There are three major ways one could work around this:

1. Just fully qualify the table name in the Views table definition. For example, for a table 'users' in the namespace 'people', do:

$data['people.users']['table']['base'] = ...

This fails because Views creates a table with the given table name to track its data, and you can't have a dot in a MySQL table name.

2. Use 'table formula' to give the fully-qualified name. This fails because table formula is only used on joins, not on the primary table in the query.

3. Add a new parameter to the table definition to specify the namespace, and take it into account when building queries. I've taken this route in the attached patch.

Additionally, Views has a naming limitation in that it keeps *all* available tables in a global array, which means you can't access a table in an external database with a name that is the same as one that already provided by Drupal or Views, such as 'users'. This is a bug inasmuch as there isn't any alternative way to alias a table name, as you can with fields. So, this patch also includes a "real table" parameter that is analogous to "real field".

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Mołot’s picture

Status: Active » Needs review

Changing status to send patch to testbot.

Status: Needs review » Needs work

The last submitted patch, views-sql-namespace.patch, failed testing.

Mołot’s picture

65 exceptions are not so bad, given that function definitions changed.
263 fails means there is no painless way to introduce it. If your patch is meant to be evolution (minor version bump) not revolution (7.x-4.x bump), it shouldn't render any existing code unusavle.

Most common error is "Base table or view not found" - it means you broken views for pretty much anyone NOT using your new parameters. Please make them optional, and make views work as they were if not provided.

Mołot’s picture

Status: Needs work » Needs review

views-sql-namespace.patch queued for re-testing.

Requesting re-test to make sure it's not a temporary MySQL glitch in testbot.

Status: Needs review » Needs work

The last submitted patch, views-sql-namespace.patch, failed testing.

machinehum’s picture

The new params are indeed optional, I am running many Views both with and without them. :) I'll take a look at the failures and see what I can figure out. Thanks!

machinehum’s picture

Oh, this was a patch against 7.x-3.6, not 3.7. Let me generate a new one against 3.7.

Mołot’s picture

Consider generating one against 3.x too. I bet it'll make it easier for maintainers to integrate it into new version.
And I really prefer PostgreSQL and db2 over MySQL, so, well, I'll be glad to help you if I can.

machinehum’s picture

Okay, here's a p1 patch against Views 7.x-3.7.

machinehum’s picture

3.x, okay I'll look into that as well. Thanks.

Mołot’s picture

Status: Needs work » Needs review

Remember to always set status to "needs review" when submitting new patch file. Only then testbots will care about automatic review of your patch.

And when submitting 7.x-3.x patch, be sure to set issue branch to 7.x-3.x too (yea I know, obvious, but it's less frustrating to tell things everybody knows than to be surprised).

Status: Needs review » Needs work

The last submitted patch, views-7.x-3.7-sql-namespace.patch, failed testing.

Mołot’s picture

Status: Needs work » Needs review

You have patch in patch you know. It makes system go crazy. Done that myself too ;)

Here is how I make my patches after trial and error:
1) checkout fresh project version from GIT
2) manually apply my changes (or semi manually - by hand cutting out meaningless changes from temporary patch file)
3) commit
4) make a patch between commits

At least this works for me and allows me to create patches without white character changes and alike.
And it helps to include 3 ~ 5 lines of context. You are not doing it, it seems, so things like @@ -1614,3 +1643,7 may get inserted anywhere between blank line and } if patcher thinks it's reasonably close to line numbers you provided...

Mołot’s picture

Status: Needs review » Needs work

Fixing status I accidentaly messed up.
Patch needs to be fixed, so it is "needs work"

Damien Tournoud’s picture

Title: SQL non-compliance breaks use of Views with existing PostgreSQL and Oracle databases » Use Views to list data from another database namespace
Version: 7.x-3.7 » 7.x-3.x-dev
Category: bug » feature
Priority: Major » Normal

It is not obvious what your use case is to begin with. I assume you want to fetch data from another database namespace, most likely out of some legacy system? Could you give more details about what this data is and how you want to use it?

Views doesn't support namespaces at all, as you already noted. But (from memory) it does support multiple database connections, so you might be able to use that instead.

Mołot’s picture

Simplest use-case is to use namespaces in place of db_prefix. Drupal already recognizes there is a need for multiple data sets in one database and provides crippled support of it. Why not to use full support the true-SQL provides?

My use case is - I need one data set for purely CMS data, and other to index machine parts in a way that'll make it accessible both by CMS and by software in repair shop, sales department and so on. And I see no reason to make separate databases out of them, but I will want to join CMS tables with machine parts ones. Classic example of separation by namespaces. There is a tool for that. Drupal was written for MySQL but since Drupal 7 it is going in the direction of other, more advanced RDBMS. And Views in D8 core proves that Views may pretty much cripple that trend.

I agree that other way around it would be to make each namespace different db connection in core, but it would mess the ability to make cross-namespace joins. Default namespace in settings.php and namespace support in drupal's core would be great, but even then significant changes would be needed in Views to use it. Changes quite similar to OP's idea presented here, so why not implement them and then go improving core? It'll give us useable something fast at least. Code seems pretty much ready, except for patch generating skills far from perfect.

Move bug to a separate issue

you can't access a table in an external database with a name that is the same as one that already provided

It's a bug, not a feature. I strongly suggest creating new issue for it for further discussion.
Use case - well, contrib modules does not know about each other and they might collide easily.

Damien Tournoud’s picture

@Mołot: You are mistaken, MySQL has namespaces, or more precisely what it calls Database is actually a Schema. What MySQL doesn't have is the concept of Database (in the sense of PostgreSQL and Oracle - and what SQL Server calls Instance).

And Drupal itself does support namespaces properly. The database prefix can contain a dot (".") to indicate a namespace separator.

Mołot’s picture

@Damien Tournoud - MySQL have 2 step naming, PostgreSQL, Oracle and so on 3 step. That's what matters here. Sorry if my lack of formality was misleading or seemed lazy. What given segment actually is, conceptually, according to ISO/IEC 9075:2011 simply seemed unimportant to me in this very case.

And I never got Drupal to properly join between namespaces, so either I did something wrong or Drupal is quite far from "proper support". Or, at least, from "full support" of namespaces.

@machinehum - be so kind and post link when (if) you'll move bug part to separate issue. I know managing 2 patches in the same code area may be hard, but I really think that table name collisions are bug that requires fixing.

machinehum’s picture

The use case is one that exists in any organization of any size. We have "legacy" databases with some data we want to display to users through Drupal Views, yes. If by "legacy" you mean our real, business-critical, properly-designed databases that use SQL-compliant three-tier naming as opposed to the disposable toy MySQL database that serves a couple hundred static pages through Drupal.

I'll work on a clean patch.

machinehum’s picture

Status: Needs work » Needs review
FileSize
4.02 KB

Created a new issue for the table name collision bug, this one will concentrate on adding that third level of naming. Here's a git patch as suggested at http://drupal.org/project/views/git-instructions .

laceysanderson’s picture

I tried this patch on my own Drupal installation and it worked perfectly!

My System:
Drupal 7.24
Views 7.x-3.x (pulled from git on 7Dec2013)
PostgreSQL 9.1.5

Setup: I have Drupal in the public schema of my PostgreSQL database and other tables in a "chado" schema. I added a very simple views integration definition to my module_views_data function for a single table and it's primary key. Then I made a simple view with the unformatted style for that table with the only field being the primary key.

Result of patch: Where before I experienced an error and inability to load the table, once I applied the patch, I was able to select from the table through views error free!

IMPORTANT NOTE (for others attempting to use this patch): To use this functionality you need to add the following to your table definition:
$data['example_table']['table']['base']['search_path'] = 'my_schema_name';

laceysanderson’s picture

The previous patch only worked for integration of views base tables. I've added an extra check that allows it to work for non-base tables as well. I didn't change any of the underlying logic -just added an extra check.

Now, you can set the search path for base tables (previous patch included in this one):
$data['example_table']['table']['base']['search_path'] = 'my_schema_name';
And non-base tables such as linking tables, etc. (new to this patch):
$data['example_table']['table']['search_path'] = 'my_schema_name';

nathanweeks’s picture

I would like to assist in getting @laceysanderson's patch incorporated into Views. Could a Drupal core contributor comment on what would need to be done to make this happen?

mbaynton’s picture

FileSize
5.89 KB

For those using this patch, it is incomplete because molot requested it be split into two issues in #16. This patch alone will only work if your tables in separate namespaces are all named differently; you also need 1972880 to be able to work with tables in different namespaces having the same name.

For convenience, I'm including a patch that merges the latest passing versions of the individual patches from both issues.

laceysanderson’s picture

Just an update on this, the patch in #24 breaks the functionality I had working in #22. I am looking into why this is the case and working on a patch from my end.
Thanks @mbaynton for bringing up the other issue!

Furthermore, the above patch does not apply cleanly to the newest 7.x-3.x-dev (96a54e041b171eb47c6a00805b9c4731c81d9283) and testing seems to be postponed due to another test failure on the views branch Testbot Report for Views 7.x-3.x

laceysanderson’s picture

The patch in #1972880-2: You can't access a table in an external database with a name that is the same as one that already provided also does not apply cleanly to the current Views 7.x-3.x-dev. Since the table collision is only a problem if you have two tables (one in each integrated database) both with Drupal Views integration, I don't think we should combine the patches at this time. Furthermore, there does not seem to be a consensus on that issue for the best way to solve such collisions. They were separated out into different issues for a reason and applying two patches instead of one seems like less work then maintaining a merged patch as well as individual patches.

I'm going to retest the patch in #22 to confirm that all is well on the newest views 7.x-3.x dev version.

The last submitted patch, 22: views-sql-compliant-three-tier-naming-1971160-22.patch, failed testing.

njbooher’s picture

The patch in #22 turns $right_table into a string, which breaks relationships like views_handler_relationship_node_term_data which use a subquery as a right table.

The attached patch avoids interfering with other modules that aren't using search_path by only prepending the search_path if search_path is defined.

laceysanderson’s picture

I tested the patch in #30 and it works for my purposes :-)

jungle’s picture

Status: Needs review » Needs work

Patch #30 not working with views 7.x-3.20, it cannot be applied.

jungle’s picture

BTW, the patch #30 works with views 7.x-3.18

laceysanderson’s picture

Hi @jungle, we had an updated version of this patch contributed by our Tripal Community by https://github.com/abretaud. I've attached it here for you :-)

jungle’s picture

Wow, Lacey, Thank you and Tripal!

Especially, Thank you, @laceysanderson, very much for your contributions to the Tripal project.

jungle’s picture

Status: Needs work » Needs review

Patch #34 Works for me.