diff options
-rw-r--r-- | includes/database/database.inc | 31 | ||||
-rw-r--r-- | includes/database/query.inc | 7 | ||||
-rw-r--r-- | includes/database/select.inc | 41 | ||||
-rw-r--r-- | modules/openid/openid.module | 2 | ||||
-rw-r--r-- | modules/simpletest/tests/database_test.test | 2 |
5 files changed, 65 insertions, 18 deletions
diff --git a/includes/database/database.inc b/includes/database/database.inc index d0348cf7c..24eed8af2 100644 --- a/includes/database/database.inc +++ b/includes/database/database.inc @@ -779,6 +779,20 @@ abstract class DatabaseConnection extends PDO { } /** + * Escapes a field name string. + * + * Force all field names to be strictly alphanumeric-plus-underscore. + * For some database drivers, it may also wrap the field name in + * database-specific escape characters. + * + * @return + * The sanitized field name string. + */ + public function escapeField($field) { + return preg_replace('/[^A-Za-z0-9_.]+/', '', $field); + } + + /** * Escapes characters that work as wildcard characters in a LIKE pattern. * * The wildcard characters "%" and "_" as well as backslash are prefixed with @@ -2423,7 +2437,7 @@ function db_set_active($key = 'default') { } /** - * Restricts a dynamic table, column, or constraint name to safe characters. + * Restricts a dynamic table name to safe characters. * * Only keeps alphanumeric and underscores. * @@ -2438,6 +2452,21 @@ function db_escape_table($table) { } /** + * Restricts a dynamic column or constraint name to safe characters. + * + * Only keeps alphanumeric and underscores. + * + * @param $field + * The field name to escape. + * + * @return + * The escaped field name as a string. + */ +function db_escape_field($field) { + return Database::getConnection()->escapeField($field); +} + +/** * Escapes characters that work as wildcard characters in a LIKE pattern. * * The wildcard characters "%" and "_" as well as backslash are prefixed with diff --git a/includes/database/query.inc b/includes/database/query.inc index 5fa846548..43c54f8a8 100644 --- a/includes/database/query.inc +++ b/includes/database/query.inc @@ -21,10 +21,11 @@ interface QueryConditionInterface { * * This method can take a variable number of parameters. If called with two * parameters, they are taken as $field and $value with $operator having a value - * of =. + * of IN if $value is an array and = otherwise. * * @param $field - * The name of the field to check. + * The name of the field to check. If you would like to add a more complex + * condition involving operators or functions, use where(). * @param $value * The value to test the field against. In most cases, this is a scalar. For more * complex options, it is an array. The meaning of each element in the array is @@ -1255,7 +1256,7 @@ class DatabaseCondition implements QueryConditionInterface, Countable { $placeholders[] = $placeholder; } } - $condition_fragments[] = ' (' . $condition['field'] . ' ' . $operator['operator'] . ' ' . $operator['prefix'] . implode($operator['delimiter'], $placeholders) . $operator['postfix'] . ') '; + $condition_fragments[] = ' (' . $connection->escapeField($condition['field']) . ' ' . $operator['operator'] . ' ' . $operator['prefix'] . implode($operator['delimiter'], $placeholders) . $operator['postfix'] . ') '; } } } diff --git a/includes/database/select.inc b/includes/database/select.inc index 2961bb1ef..48bd04daf 100644 --- a/includes/database/select.inc +++ b/includes/database/select.inc @@ -445,6 +445,29 @@ interface SelectQueryInterface extends QueryConditionInterface, QueryAlterableIn public function preExecute(SelectQueryInterface $query = NULL); /** + * Helper function to build most common HAVING conditional clauses. + * + * This method can take a variable number of parameters. If called with two + * parameters, they are taken as $field and $value with $operator having a value + * of IN if $value is an array and = otherwise. + * + * @param $field + * The name of the field to check. If you would like to add a more complex + * condition involving operators or functions, use having(). + * @param $value + * The value to test the field against. In most cases, this is a scalar. For more + * complex options, it is an array. The meaning of each element in the array is + * dependent on the $operator. + * @param $operator + * The comparison operator, such as =, <, or >=. It also accepts more complex + * options such as IN, LIKE, or BETWEEN. Defaults to IN if $value is an array + * = otherwise. + * @return QueryConditionInterface + * The called object. + */ + public function havingCondition($field, $value = NULL, $operator = NULL); + + /** * Clone magic method. * * Select queries have dependent objects that must be deep-cloned. The @@ -906,10 +929,7 @@ class SelectQuery extends Query implements SelectQueryInterface { /* Implementations of QueryConditionInterface for the WHERE clause. */ public function condition($field, $value = NULL, $operator = NULL) { - if (!isset($num_args)) { - $num_args = func_num_args(); - } - $this->where->condition($field, $value, $operator, $num_args); + $this->where->condition($field, $value, $operator); return $this; } @@ -942,11 +962,8 @@ class SelectQuery extends Query implements SelectQueryInterface { /* Implementations of QueryConditionInterface for the HAVING clause. */ - public function havingCondition($field, $value = NULL, $operator = '=') { - if (!isset($num_args)) { - $num_args = func_num_args(); - } - $this->having->condition($field, $value, $operator, $num_args); + public function havingCondition($field, $value = NULL, $operator = NULL) { + $this->having->condition($field, $value, $operator); return $this; } @@ -1296,13 +1313,13 @@ class SelectQuery extends Query implements SelectQueryInterface { $fields = array(); foreach ($this->tables as $alias => $table) { if (!empty($table['all_fields'])) { - $fields[] = $alias . '.*'; + $fields[] = $this->connection->escapeTable($alias) . '.*'; } } foreach ($this->fields as $alias => $field) { // Always use the AS keyword for field aliases, as some // databases require it (e.g., PostgreSQL). - $fields[] = (isset($field['table']) ? $field['table'] . '.' : '') . $field['field'] . ' AS ' . $field['alias']; + $fields[] = (isset($field['table']) ? $this->connection->escapeTable($field['table']) . '.' : '') . $this->connection->escapeField($field['field']) . ' AS ' . $this->connection->escapeField($field['alias']); } foreach ($this->expressions as $alias => $expression) { $fields[] = $expression['expression'] . ' AS ' . $expression['alias']; @@ -1331,7 +1348,7 @@ class SelectQuery extends Query implements SelectQueryInterface { // Don't use the AS keyword for table aliases, as some // databases don't support it (e.g., Oracle). - $query .= $table_string . ' ' . $table['alias']; + $query .= $table_string . ' ' . $this->connection->escapeTable($table['alias']); if (!empty($table['condition'])) { $query .= ' ON ' . $table['condition']; diff --git a/modules/openid/openid.module b/modules/openid/openid.module index ebd63f0bb..45b6714b2 100644 --- a/modules/openid/openid.module +++ b/modules/openid/openid.module @@ -550,7 +550,7 @@ function openid_association($op_endpoint) { // Remove Old Associations: db_delete('openid_association') - ->condition('created + expires_in', REQUEST_TIME, '<') + ->where('created + expires_in < :request_time', array(':request_time' => REQUEST_TIME)) ->execute(); // Check to see if we have an association for this IdP already diff --git a/modules/simpletest/tests/database_test.test b/modules/simpletest/tests/database_test.test index 1005553d4..09c310cd5 100644 --- a/modules/simpletest/tests/database_test.test +++ b/modules/simpletest/tests/database_test.test @@ -1835,7 +1835,7 @@ class DatabaseSelectComplexTestCase extends DatabaseTestCase { $task_field = $query->addField('t', 'task'); $query->orderBy($count_field); $query->groupBy($task_field); - $query->havingCondition('COUNT(task)', 2, '>='); + $query->having('COUNT(task) >= 2'); $result = $query->execute(); $num_records = 0; |