[wp-trac] [WordPress Trac] #50789: Improve WPDB logic around information_schema

WordPress Trac noreply at wordpress.org
Mon Jul 27 17:43:38 UTC 2020


#50789: Improve WPDB logic around information_schema
--------------------------+-----------------------------
 Reporter:  andy          |      Owner:  (none)
     Type:  defect (bug)  |     Status:  new
 Priority:  normal        |  Milestone:  Awaiting Review
Component:  Database      |    Version:  trunk
 Severity:  normal        |   Keywords:
  Focuses:  multisite     |
--------------------------+-----------------------------
 WooCommerce uses a query on `information_schema.table_constraints` to
 determine whether it needs to add a foreign key constraint to one of its
 tables.

 {{{
 SELECT
   COUNT(*) AS fk_count
 FROM
   information_schema.TABLE_CONSTRAINTS
 WHERE
   CONSTRAINT_SCHEMA = ''
   AND CONSTRAINT_NAME = 'fk_wp_12345_wc_download_log_permission_id'
   AND CONSTRAINT_TYPE = 'FOREIGN KEY'
   AND TABLE_NAME = 'wp_12345_wc_download_log'
 }}}

 `$wpdb->get_table_from_query` returns `information_schema` which is not a
 table, it is a database containing the table `TABLE_CONSTRAINTS`. So it
 seems there is room to improve this method to extract the table name in
 cases where it is preceded by a database name. However, this is not the
 goal of this ticket. In the specific case of `information_schema` tables,
 we're more interested in the table referenced in the `WHERE` clause.

 My use case involves a `wpdb` drop-in, WordPress.com's hyperdb, which was
 the original source of this method when it was added in [30345]. We use
 hyperdb to map queries to database servers using table names as map keys.
 Given a table like `wp_12345_posts` we connect to the right database.

 The database `information_schema` exists in all database servers. When
 WooCommerce queries the table `table_constraints` it's looking for
 information about the table `wp_12345_wc_download_log`. To route the query
 to the appropriate database server, we are interested in this table name.

 I would propose adding this before the first `preg_match` in
 `get_table_from_query`:

 {{{
                 // SELECT FROM information_schema.* WHERE TABLE_NAME =
 'wp_12345_foo'
                 if ( preg_match('/^\s*'
                                 .
 'SELECT.*?\s+FROM\s+`?information_schema`?\.'
                                 .
 '.*\s+TABLE_NAME\s*=\s*["\']([\w-]+)["\']/is', $q, $maybe) )
                         return $maybe[1];
 }}}

 This returns `wp_12345_wc_download_log` which allows us to route the query
 to the correct database server.

 I am able to patch WordPress.com's drop-in to check this pattern before
 calling the parent method in core's `wpdb`. So there is no need to rush on
 our behalf.

 Does anyone know of a use case that relies on the existing implementation?

 It might be argued that a caller of this function would expect the return
 to be `TABLE_CONSTRAINTS` in this case. However, I was unable to find any
 tickets requesting a fix for the current behavior. I believe the best fix
 would be to return the table name from the `WHERE` clause.

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/50789>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list