Schema function findTables fails on postgres - wrong SQL

Josh Waihi - December 4, 2008 - 04:40
Project:Drupal
Version:7.x-dev
Component:postgresql database
Category:bug report
Priority:critical
Assigned:Josh Waihi
Status:closed
Issue tags:PostgreSQL Surge
Description

the schema function findTables() uses this SQL:
SELECT table_name FROM information_schema.tables WHERE table_schema = :database AND table_name LIKE :table_name
however in most cases table_schema will = public and so the function fails, this is because the database is stored in the table_catalog column instead of the table_schema column.

so the postgres schema driver needs to have its own findTables function that changes the SQL

AttachmentSize
schema.inc_.patch1.19 KB
Testbed results
schema.inc_.patchre-testing

#1

Damien Tournoud - December 4, 2008 - 20:50
Title:schema function findTables fails on postgres - wrong SQL» PostgreSQL surge #9: schema function findTables fails on postgres - wrong SQL

As discussed on the IRC, we need to think about the relationship between the concepts of "Database", "Schema", "Drupal prefix".

The PostgreSQL concept of Schema (defined by the SQL standard) is quite close to the concept of "Drupal prefix": you can do queries across tables in different schemas in the same database, but you can't do queries across tables in different databases. MySQL concept of "Database" is more a "Schema" than anything else.

PostgreSQL: database (closed container) -> schema (open container) -> tables
MySQL: database (open container) -> tables
Drupal: prefix (open container) -> tables

Also related: #286986: MySQL: SHOW TABLES LIKE database.tablename doesn't work, that try to unify tableExists() and columnExists() across database engines.

#2

Josh Waihi - December 7, 2008 - 20:43

ok so this is quite a big patch. it fixes the schema/prefix issues around findTables(), tableExists() and columnExists() also there is a function now to defuse $db_prefix for any database.prefix type prefixes. there still is issues surrounding using schemas in postgres such as they don't install. its on my todo list

AttachmentSize
schema.inc_.patch 7.51 KB
Testbed results
schema.inc_.patchfailedFailed: Failed to install HEAD. Detailed results

#3

Josh Waihi - December 7, 2008 - 23:05

ok that last patch was crap, after talking to DamZ on IRC, I came up with this, its better, not sure if its right just yet

AttachmentSize
schema.inc_.patch 6.25 KB
Testbed results
schema.inc_.patchfailedFailed: Invalid PHP syntax. Detailed results

#4

System Message - December 7, 2008 - 23:20
Status:needs review» needs work

The last submitted patch failed testing.

#5

lilou - December 7, 2008 - 23:49

@josh : your patch failed because :

':table_name' => this->explodeTable($table_expression)->table,

$this

#6

Josh Waihi - December 8, 2008 - 03:42
Status:needs work» needs review

the idea of making 'database.schema.table ' apart of prefixTables sounded great BUT, we overlooked indexes, you can't say for example: CREATE INDEX drupal7.public.simpletest305454batch_token_idx.... because the dot(.) would be a syntax error.

suggestions?

#7

Josh Waihi - December 8, 2008 - 03:42
Status:needs review» needs work

#8

Josh Waihi - December 9, 2008 - 22:16

ok this patch moves things around a bit in the very core of DBTNG. if should pass with 4 fails on the 'Module list functionality' simple test in system, the query seems fine but the tables actually don't exist that I can see (unless they are removed after tests) I would love for someone to review and help me figure out the issue.

Explaination:
this patch proposes that every table is referenced like 'database.schema.tablename' or 'database.tablename' for MySQL. This is so that in MySQL querys can be queried across databases and in PostgreSQL, querys can be queried aross schemas.
In order to do this, the prefixTables function was re-written to so that each {table} became database.schema.tablename.

I think the findTables function still isn't right which is why there is 4 fails.

look forward to the feedback

AttachmentSize
schema.inc_.patch 12.91 KB
Testbed results
schema.inc_.patchfailedFailed: 7624 passes, 4 fails, 0 exceptions Detailed results

#9

Josh Waihi - December 10, 2008 - 00:55

OMG this one passes

AttachmentSize
schema.inc_.patch 13.71 KB
Testbed results
schema.inc_.patchfailedFailed: Failed to install HEAD. Detailed results

#10

Crell - December 10, 2008 - 03:48

The ternary at the top of prefixTables() is slower than doing an if (empty($info)) { ... } check. Let's do that instead.

+1 on making prefixTables a method rather than a static method.

db_result() is deprecated. findTables() should be using db_query()->fetchField() instead.

findTables() should only call explodeTable() once and save the result. Calling it 3 times results in unnecessary parsing. Optionally explodeTable() could save the parsed data to an object property and just return it next time. Or both. :-)

The docblock for explodeTable() doesn't explain what "Better" means. Huh?

Can you include a comment describing why the mysql prefixTables() has to be different than the global one?

I think I like what I'm seeing here. It's a good direction for schema to move, but it still has a long way to go.

#11

Josh Waihi - December 10, 2008 - 04:35
Status:needs work» needs review

as per Crell's feedback

AttachmentSize
schema.inc_.patch 13.1 KB
Testbed results
schema.inc_.patchfailedFailed: 6876 passes, 3 fails, 6 exceptions Detailed results

#12

System Message - December 10, 2008 - 05:15
Status:needs review» needs work

The last submitted patch failed testing.

#13

Josh Waihi - December 11, 2008 - 02:46
Status:needs work» needs review

spelling errors fixed from previos patch - rename tables sql error found on postgres also fix

AttachmentSize
schema.inc_.patch 13.85 KB
Testbed results
schema.inc_.patchre-testing

#14

CalebD - December 18, 2008 - 20:34

Small code style issues. Comments should be styled as sentences (capitalize first word, period at the end). Example problem:

+      // require schema and database info

Also, we should avoid shorthand variable names, like $pfx and $tbl_bits.

I do like that this is getting us closer to compatibility with the SQL standard for RDBMSs that support it.

#15

Damien Tournoud - December 19, 2008 - 02:10

Here is something a little bit more with what I had in mind. With a little bit of condition magic (warning: you can't use db_select() in that context, because it prefixes all tables), it's possible to abstract all particularities of PostgreSQL and MySQL regarding the information schema. This would probably work out-of-the-box too with SQL Server.

Warning 1: this is untested
Warning 2: it is 3am, so it could even not make sense at all

AttachmentSize
342503-information-schema-magic.patch 6.8 KB
Testbed results
342503-information-schema-magic.patchfailedFailed: Failed to install HEAD. Detailed results

#16

Josh Waihi - December 19, 2008 - 02:32
Status:needs review» needs work

@Damien: I like what you've done, I can see a couple of things that won't work in Postgres but I'll review and re-submit anyway

#17

Josh Waihi - December 19, 2008 - 05:14
Status:needs work» needs review

fixed bugs created by 3am madness including syntax etc, works on postgres

AttachmentSize
information-schema-magic.patch 7.26 KB
Testbed results
information-schema-magic.patchfailedFailed: 7889 passes, 4 fails, 0 exceptions Detailed results

#18

System Message - December 19, 2008 - 08:50
Status:needs review» needs work

The last submitted patch failed testing.

#19

Josh Waihi - December 20, 2008 - 03:33
Status:needs work» needs review

the reason this patched failed was because of two things:
* The Module list functionality test attempted to find a table and prefixing that table before search where as now all the prefixing is kept within the schema and shouldn't be used outside of it.
* The operator (2nd param) of DamZ's function buildTableNameCondition wasn't being passed to the condition meaning '=' was being used instead of 'LIKE'

AttachmentSize
schema-magic.patch 8.09 KB
Testbed results
schema-magic.patchfailedFailed: Failed to apply patch. Detailed results

#20

Damien Tournoud - December 20, 2008 - 03:45
Status:needs review» needs work

Ok, in fact it is a mistake to prefix inside buildTableNameCondition() because that function assume that the table name passed to it is already prefixed, so that dotted tables can be split correctly.

So the prefixing should be moved back into tableExists() and columnExists() (those get as input a non-prefixed table). findTable() is good because, as a (well documented) special case, it actually takes an already prefixed table as input.

No changes are necessary in the tests.

#21

Josh Waihi - December 20, 2008 - 04:01
Status:needs work» needs review

ok try again

AttachmentSize
schema-magic.patch 7.32 KB
Testbed results
schema-magic.patchfailedFailed: 7891 passes, 4 fails, 0 exceptions Detailed results

#22

Damien Tournoud - December 20, 2008 - 04:07
Status:needs review» needs work

You will need to manually add the enclosing "{}" before calling prefixTables(). Also, the MySQL implementation of buildTableNameCondition() was not fixed.

#23

Josh Waihi - December 20, 2008 - 04:20
Status:needs work» needs review
AttachmentSize
schema-magic.patch 7.3 KB
Testbed results
schema-magic.patchfailedFailed: Invalid PHP syntax. Detailed results

#24

System Message - December 20, 2008 - 04:27
Status:needs review» needs work

The last submitted patch failed testing.

#25

Damien Tournoud - December 20, 2008 - 04:27
Status:needs work» needs review

Slave #9 is apparently buggy.

#26

Damien Tournoud - December 20, 2008 - 14:48

Resubmit to force retesting.

AttachmentSize
schema-magic_1.patch 7.3 KB
Testbed results
schema-magic_1.patchfailedFailed: Invalid PHP syntax. Detailed results

#27

Dries - December 20, 2008 - 18:45

This patch does the right thing. However, I think the different buildTableNameCondition() functions should have more phpdoc. A lot of the knowledge (and depth of information) captured in this issue is completely lost in the phpDoc. That is unfortunate because I found the information in comment #1 to be key in order to be able to understand this patch. The information in #1 was not new to me, but nonetheless, I was necessary to refresh my memory and to contrast the two databases. It helped tremendously. In other words, please explain _why_ this function is useful, _why_ the code is structed like this, explain terminology like information_schema a tiny bit better, and make sure people are setup to be able to understand this patch. Thanks!

All things considered, this issue illustrates _exactly_ why we should have more than one database driver in core. It forces us to design and architect things properly. It we'd only support MySQL, our database abstraction layer would probably be a failure.

Keep up the good work, folks.

#28

Josh Waihi - December 20, 2008 - 21:21

Hope these comments help clear things up

AttachmentSize
schema-magic.patch 8.65 KB
Testbed results
schema-magic.patchfailedFailed: Invalid PHP syntax. Detailed results

#29

keith.smith - December 20, 2008 - 21:52
Status:needs review» needs work

+   * The information_schema is a SQL standard that provides information about the
+   * database server and the databases, schemas, tables, columns and users within
+   * it. This makes information_schema a useful tool to use across the drupal
+   * database drivers and is used by a few different functions. The function below
+   * describes the conditions to be meet when querying information_schema.tables
+   * for drupal tables or information associated with drupal tables. Even though
+   * this is the standard method, not all databases follow standards and so this
+   * method should be overwritten by a database driver if the database provider
+   * uses alternate methods. Because information_schema.tables is used in a few
+   * different functions, a database driver will only need to override this function
+   * to make all the others work. For example see includes/databases/mysql/schema.inc.

Per coding standards, "drupal" is written as "Drupal".

#30

Josh Waihi - December 21, 2008 - 01:38
Status:needs work» needs review

Upper case Drupal

AttachmentSize
schema-magic.patch 8.65 KB
Testbed results
schema-magic.patchfailedFailed: Failed to apply patch. a href=http://testing.drupal.org/pifr/file/1/schema-magic_3.patchDetailed results/a

#31

System Message - December 24, 2008 - 01:55
Status:needs review» needs work

The last submitted patch failed testing.

#32

Damien Tournoud - December 30, 2008 - 04:08
Status:needs work» needs review

Straight reroll... the last fail was a testing glitch.

AttachmentSize
342503-information-schema-magic.patch 8.44 KB

#33

drewish - January 5, 2009 - 03:21

tagging.

#34

Damien Tournoud - January 5, 2009 - 11:24
Title:PostgreSQL surge #9: schema function findTables fails on postgres - wrong SQL» Schema function findTables fails on postgres - wrong SQL

I really think this is ready. Can we have someone to test it manually (drewish, please help if you can).

#35

Josh Waihi - January 6, 2009 - 21:11

I tested this this morning. Core still has 5 fails under postgres, after applying this patch, that is reduced to 2. So am keen to get this commited!

#36

Shiny - January 6, 2009 - 22:35
Status:needs review» reviewed & tested by the community

tested on PostgreSQL 8.2.9.

tested lotsa db_create_table & db_drop_table from hook_install/uninstall. --

all worked as expected.

#37

Josh Waihi - January 7, 2009 - 02:40

correction! with patch applied there is only 1 fail to HEAD with PostgreSQL! #355225: Inconsistant Insert Queries Between Database Drivers is addressing that single fail

#38

webchick - January 7, 2009 - 02:47

This is a pretty large patch that changes a lot of DBTNG internals. I'd really like Crell's input on this before committing.

#39

Josh Waihi - January 7, 2009 - 04:48

err, someone mentioned to me that no one has tested mysql yet. was a good point because there was a syntax error in the mysql schema.inc.
After correcting the syntax error I ran the entire simpletest suite and got 8162 passes, 0 fails, and 0 exceptions.

AttachmentSize
342503-information-schema-magic_2.patch 8.73 KB

#40

Crell - January 7, 2009 - 07:19
Status:reviewed & tested by the community» needs work

For MySQL readers, the concept of "schema" will be totally alien. (What Postgres calls a schema, MySQL calls a database. And then there is no equivalent for what Postgres calls a database, AFAIK.) That's especially true given the Drupal usage of the word "schema". I'm not entirely sure how we should address that, but as a MySQL guy I found some of the comments and logic a bit confusing as a result. [Edit: At least from reading schema.inc. The comment in for mysql/schema.inc explains it. That may be sufficient; I'm just flagging it as a possible confusion point we should consider.]

I do not like the string concatenation in tableExists() for the conditional. I completely understand why we're doing it, but given how much effort we're putting into avoiding string manipulation for queries it still makes me uneasy. At the very least we should document why we're doing something that we heartily discourage elsewhere.

The comments for findTables() say that the caller is responsible for handling table prefixing. Since prefixTables() is now an object method rather than class method with this patch (which I very much agree with), should we make it public so that said caller can prefix the table properly? Seems sensible to me to do.

The docblock for DatabaseSchema_mysql::buildTableNameCondition() is invalid, as it has a multi-line first description.

So not quite RTBC, but the approach makes sense to me provided we document some of the somewhat uncooth query building we're doing properly.

#41

Josh Waihi - January 8, 2009 - 02:25

I guess then it would confuse most MySQL people that they store their database names in a column called table_schema in the information_schema. As mentioned in #1, what postgres does is more SQL standard and MySQL concept of a database if more like a schema. It even be educating to those MySQL people who look into the code to learn this.

re-roll with changes requested by Crell

AttachmentSize
342503-information-schema-magic_3.patch 9.79 KB
Testbed results
342503-information-schema-magic_3.patchpassedPassed: 8162 passes, 0 fails, 0 exceptions a href=http://testing.drupal.org/pifr/file/1/342503-information-schema-magic_3.patchDetailed results/a

#42

Josh Waihi - January 8, 2009 - 02:27
Status:needs work» needs review

forgot to set to review

#43

Crell - January 8, 2009 - 04:53
Status:needs review» reviewed & tested by the community

I'd say this is ready now. Nice work, guys!

#44

Dries - January 8, 2009 - 09:52
Status:reviewed & tested by the community» fixed

Committed to CVS HEAD. Thanks! :)

#45

System Message - January 22, 2009 - 10:00
Status:fixed» closed

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

 
 

Drupal is a registered trademark of Dries Buytaert.