CRM-18811. Permit spaces in table and column aliases.
authorChris Burgess <chris@giantrobot.co.nz>
Mon, 13 Jun 2016 04:32:54 +0000 (16:32 +1200)
committerChris Burgess <chris@giantrobot.co.nz>
Mon, 13 Jun 2016 04:33:12 +0000 (16:33 +1200)
Spaces are permitted provided the aliases are surrounded by backticks. This is not intended to be a complete representation of what MySQL permits, it's just expanding to permit things that CiviCRM actually generates.

CRM/Utils/Rule.php
tests/phpunit/CRM/Utils/TypeTest.php

index 0ea7c32e3cc337c65f8620859dd4e83ff5227646..a1d8a9a10318b5715ad509ee361a9de9d3e13482 100644 (file)
@@ -100,10 +100,15 @@ class CRM_Utils_Rule {
       return FALSE;
     }
 
-    // Ensure the string contains only valid characters:
-    // For column names: alphanumeric and underscores
-    // For aliases: backticks, alphanumeric hyphens and underscores.
-    if (!preg_match('/^((`[\w-]{1,64}`|[\w-]{1,64})\.)?(`[\w-]{1,64}`|[\w-]{1,64})$/i', $str)) {
+    // Ensure $str conforms to expected format. Not a complete expression of
+    // what MySQL permits; this should permit the formats CiviCRM generates.
+    //
+    // * Table name prefix is optional.
+    // * Table & column names & aliases:
+    //   * Composed of alphanumeric chars, underscore and hyphens.
+    //   * Maximum length of 64 chars.
+    //   * Optionally surrounded by backticks, in which case spaces also OK.
+    if (!preg_match('/^((`[\w- ]{1,64}`|[\w-]{1,64})\.)?(`[\w- ]{1,64}`|[\w-]{1,64})$/i', $str)) {
       return FALSE;
     }
 
index 3b6a853cecb59310480ea3d7a331146b43aabd61..e929343668a924e1b549491ca90d356eb9a9e6a2 100644 (file)
@@ -2,6 +2,8 @@
 
 /**
  * Class CRM_Utils_TypeTest
+ * @package CiviCRM
+ * @subpackage CRM_Utils_Type
  * @group headless
  */
 class CRM_Utils_TypeTest extends CiviUnitTestCase {
@@ -46,12 +48,23 @@ class CRM_Utils_TypeTest extends CiviUnitTestCase {
       array('table.`Home-street_address`', 'MysqlColumnNameOrAlias', 'table.`Home-street_address`'),
       array('`table-alias`.`Home-street_address`', 'MysqlColumnNameOrAlias', '`table-alias`.`Home-street_address`'),
       array('`table-alias`.column', 'MysqlColumnNameOrAlias', '`table-alias`.column'),
+      // Spaces also permitted, only when enclosed in backticks.
+      array('`column alias`', 'MysqlColumnNameOrAlias', '`column alias`'),
+      array('`table alias`.column', 'MysqlColumnNameOrAlias', '`table alias`.column'),
+      array('`table alias`.`column alias`', 'MysqlColumnNameOrAlias', '`table alias`.`column alias`'),
+      array('table alias.column alias', 'MysqlColumnNameOrAlias', NULL),
+      array('table alias.column_alias', 'MysqlColumnNameOrAlias', NULL),
+      array('table_alias.column alias', 'MysqlColumnNameOrAlias', NULL),
+      // Functions are not permitted.
       array('column_name, sleep(5)', 'MysqlColumnNameOrAlias', NULL),
+      // Length checking permits only 64 chars.
       array(str_repeat('a', 64), 'MysqlColumnNameOrAlias', str_repeat('a', 64)),
       array(str_repeat('a', 65), 'MysqlColumnNameOrAlias', NULL),
       array(str_repeat('a', 64) . '.' . str_repeat('a', 64), 'MysqlColumnNameOrAlias', str_repeat('a', 64) . '.' . str_repeat('a', 64)),
+      array('`' . str_repeat('a', 64) . '`.`' . str_repeat('b', 64) . '`', 'MysqlColumnNameOrAlias', '`' . str_repeat('a', 64) . '`.`' . str_repeat('b', 64) . '`'),
       array(str_repeat('a', 64) . '.' . str_repeat('a', 65), 'MysqlColumnNameOrAlias', NULL),
       array(str_repeat('a', 65) . '.' . str_repeat('a', 64), 'MysqlColumnNameOrAlias', NULL),
+      // ORDER BY can be ASC or DESC, case not significant.
       array('asc', 'MysqlOrderByDirection', 'asc'),
       array('DESC', 'MysqlOrderByDirection', 'desc'),
       array('DESCc', 'MysqlOrderByDirection', NULL),