Index: includes/database/mysql/schema.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/database/mysql/schema.inc,v
retrieving revision 1.12
diff -u -9 -p -r1.12 schema.inc
--- includes/database/mysql/schema.inc 14 Mar 2009 20:34:17 -0000 1.12
+++ includes/database/mysql/schema.inc 30 Mar 2009 21:32:24 -0000
@@ -54,19 +54,20 @@ class DatabaseSchema_mysql extends Datab
* @param $name
* The name of the table to create.
* @param $table
* A Schema API table definition array.
* @return
* An array of SQL statements to create the table.
*/
protected function createTableSql($name, $table) {
if (empty($table['mysql_suffix'])) {
- $table['mysql_suffix'] = 'DEFAULT CHARACTER SET UTF8';
+ // Store strings as UTF-8 and do case-sensitive comparision.
+ $table['mysql_suffix'] = 'DEFAULT CHARACTER SET UTF8 COLLATE utf8_bin';
}
$sql = "CREATE TABLE {" . $name . "} (\n";
// Add the SQL statement for each field.
foreach ($table['fields'] as $field_name => $field) {
$sql .= $this->createFieldSql($field_name, $this->processField($field)) . ", \n";
}
Index: includes/database/pgsql/database.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/database/pgsql/database.inc,v
retrieving revision 1.19
diff -u -9 -p -r1.19 database.inc
--- includes/database/pgsql/database.inc 26 Jan 2009 14:08:42 -0000 1.19
+++ includes/database/pgsql/database.inc 30 Mar 2009 21:32:24 -0000
@@ -91,25 +91,20 @@ class DatabaseConnection_pgsql extends D
public function driver() {
return 'pgsql';
}
public function databaseType() {
return 'pgsql';
}
public function mapConditionOperator($operator) {
- static $specials = array(
- // In PostgreSQL, 'LIKE' is case-sensitive. For case-insensitive LIKE
- // statements, we need to use ILIKE instead.
- 'LIKE' => array('operator' => 'ILIKE'),
- );
-
- return isset($specials[$operator]) ? $specials[$operator] : NULL;
+ // We don't want to override any of the defaults.
+ return NULL;
}
/**
* @todo Remove this as soon as db_rewrite_sql() has been exterminated.
*/
public function distinctField($table, $field, $query) {
$field_to_select = 'DISTINCT(' . $table . '.' . $field . ')';
// (?transactionSupport = !isset($connection_options['transactions']) || $connection_options['transactions'] !== FALSE;
parent::__construct('sqlite:'. $connection_options['database'], '', '', array(
// Force column names to lower case.
PDO::ATTR_CASE => PDO::CASE_LOWER,
));
$this->exec('PRAGMA encoding="UTF-8"');
+ $this->exec('PRAGMA case_sensitive_like=1');
// Create functions needed by SQLite.
$this->sqliteCreateFunction('if', array($this, 'sqlFunctionIf'));
$this->sqliteCreateFunction('greatest', array($this, 'sqlFunctionGreatest'));
$this->sqliteCreateFunction('pow', 'pow', 2);
$this->sqliteCreateFunction('length', 'strlen', 1);
$this->sqliteCreateFunction('concat', array($this, 'sqlFunctionConcat'));
$this->sqliteCreateFunction('substring', array($this, 'sqlFunctionSubstring'), 3);
$this->sqliteCreateFunction('rand', array($this, 'sqlFunctionRand'));
Index: modules/locale/locale.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/locale/locale.install,v
retrieving revision 1.34
diff -u -9 -p -r1.34 locale.install
--- modules/locale/locale.install 13 Feb 2009 00:45:18 -0000 1.34
+++ modules/locale/locale.install 30 Mar 2009 21:32:25 -0000
@@ -1,20 +1,16 @@
array(
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'default' => 'default',
'description' => 'A module defined group of translations, see hook_locale().',
),
'source' => array(
'type' => 'text',
- 'mysql_type' => 'blob',
'not null' => TRUE,
'description' => 'The original string in English.',
),
'version' => array(
'type' => 'varchar',
'length' => 20,
'not null' => TRUE,
'default' => 'none',
'description' => 'Version of Drupal, where the string was last used (for locales optimization).',
@@ -377,19 +372,18 @@ function locale_schema() {
'fields' => array(
'lid' => array(
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'description' => 'Source string ID. References {locales_source}.lid.',
),
'translation' => array(
'type' => 'text',
- 'mysql_type' => 'blob',
'not null' => TRUE,
'description' => 'Translation string value in this language.',
),
'language' => array(
'type' => 'varchar',
'length' => 12,
'not null' => TRUE,
'default' => '',
'description' => 'Language code. References {languages}.language.',
Index: modules/locale/locale.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/locale/locale.test,v
retrieving revision 1.19
diff -u -9 -p -r1.19 locale.test
--- modules/locale/locale.test 24 Feb 2009 16:46:52 -0000 1.19
+++ modules/locale/locale.test 30 Mar 2009 21:32:25 -0000
@@ -385,20 +385,21 @@ class LocaleTranslationFunctionalTest ex
// The English name for the language. This will be translated.
$name = $this->randomName(16);
// The native name for the language.
$native = $this->randomName(16);
// The domain prefix.
$prefix = $langcode;
// This is the language indicator on the translation search screen for
// untranslated strings. Copied straight from locale.inc.
$language_indicator = "$langcode ";
- // This will be the translation of $name.
- $translation = $this->randomName(16);
+ // This will be the translation of $name. Make sure it contains at least
+ // one lower-case character in order to check case-sensitive search.
+ $translation = $this->randomName(16) . 'x';
// Add custom language.
$this->drupalLogin($admin_user);
$edit = array(
'langcode' => $langcode,
'name' => $name,
'native' => $native,
'prefix' => $prefix,
'direction' => '0',
@@ -463,18 +464,28 @@ class LocaleTranslationFunctionalTest ex
$search = array(
'string' => $translation,
'language' => 'all',
'translation' => 'translated',
'group' => 'all',
);
$this->drupalPost('admin/build/translate/translate', $search, t('Filter'));
$this->assertNoText(t('No strings found for your search.'), t('Search found the translation.'));
+ // Ensure string search is case-sensitive.
+ $search = array(
+ 'string' => drupal_strtoupper($translation),
+ 'language' => 'all',
+ 'translation' => 'translated',
+ 'group' => 'all',
+ );
+ $this->drupalPost('admin/build/translate/translate', $search, t('Filter'));
+ $this->assertText(t('No strings found for your search.'), t("Search didn't find the translation."));
+
// Ensure translated source string doesn't appear if searching on 'only
// untranslated strings'.
$search = array(
'string' => $name,
'language' => 'all',
'translation' => 'untranslated',
'group' => 'all',
);
$this->drupalPost('admin/build/translate/translate', $search, t('Filter'));
Index: modules/simpletest/tests/database_test.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/database_test.test,v
retrieving revision 1.46
diff -u -9 -p -r1.46 database_test.test
--- modules/simpletest/tests/database_test.test 14 Mar 2009 17:45:55 -0000 1.46
+++ modules/simpletest/tests/database_test.test 30 Mar 2009 21:32:25 -0000
@@ -1989,18 +1989,46 @@ class DatabaseRegressionTestCase extends
}
/**
* Test the db_table_exists() function.
*/
function testDBTableExists() {
$this->assertTrue(db_table_exists('node'), t('Returns true for existent table.'));
$this->assertFalse(db_table_exists('nosuchtable'), t('Returns false for nonexistent table.'));
}
+
+ /**
+ * Test that string comparison is case-sensitive.
+ */
+ function testCaseSensitiviteCompare() {
+ $num_matches = db_query("SELECT COUNT(*) FROM {test} WHERE name = :name", array(':name' => 'George'))->fetchField();
+ $this->assertEqual($num_matches, 1, t('Correct number of records found with proper case.'));
+ $num_matches = db_query("SELECT COUNT(*) FROM {test} WHERE name = :name", array(':name' => 'GEORGE'))->fetchField();
+ $this->assertEqual($num_matches, 0, t('Correct number of records found with wrong case.'));
+
+ $num_matches = db_query("SELECT COUNT(*) FROM {test} WHERE name LIKE :name", array(':name' => 'Geo%'))->fetchField();
+ $this->assertEqual($num_matches, 1, t('Correct number of records found with proper case.'));
+ $num_matches = db_query("SELECT COUNT(*) FROM {test} WHERE name LIKE :name", array(':name' => 'GEO%'))->fetchField();
+ $this->assertEqual($num_matches, 0, t('Correct number of records found with wrong case.'));
+
+ $num_matches = db_select('test')
+ ->condition('name', 'Geo%', 'LIKE')
+ ->countQuery()
+ ->execute()
+ ->fetchField();
+ $this->assertEqual($num_matches, 1, t('Correct number of records found with proper case.'));
+ $num_matches = db_select('test')
+ ->condition('name', 'GEO%', 'LIKE')
+ ->countQuery()
+ ->execute()
+ ->fetchField();
+ $this->assertEqual($num_matches, 0, t('Correct number of records found with wrong case.'));
+ }
}
/**
* Query logging tests.
*/
class DatabaseLoggingTestCase extends DatabaseTestCase {
function getInfo() {
return array(
Index: modules/statistics/statistics.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/statistics/statistics.admin.inc,v
retrieving revision 1.19
diff -u -9 -p -r1.19 statistics.admin.inc
--- modules/statistics/statistics.admin.inc 26 Feb 2009 07:30:27 -0000 1.19
+++ modules/statistics/statistics.admin.inc 30 Mar 2009 21:32:25 -0000
@@ -101,20 +101,20 @@ function statistics_top_visitors() {
$output = theme('table', $header, $rows);
$output .= theme('pager', NULL, 30, 0);
return $output;
}
/**
* Menu callback; presents the "referrer" page.
*/
function statistics_top_referrers() {
- $query = "SELECT url, COUNT(url) AS hits, MAX(timestamp) AS last FROM {accesslog} WHERE url NOT LIKE :host AND url <> '' GROUP BY url";
- $query_cnt = "SELECT COUNT(DISTINCT(url)) FROM {accesslog} WHERE url <> '' AND url NOT LIKE :host";
+ $query = "SELECT url, COUNT(url) AS hits, MAX(timestamp) AS last FROM {accesslog} WHERE LOWER(url) NOT LIKE :host AND url <> '' GROUP BY url";
+ $query_cnt = "SELECT COUNT(DISTINCT(url)) FROM {accesslog} WHERE url <> '' AND LOWER(url) NOT LIKE :host";
drupal_set_title(t('Top referrers in the past %interval', array('%interval' => format_interval(variable_get('statistics_flush_accesslog_timer', 259200)))), PASS_THROUGH);
$header = array(
array('data' => t('Hits'), 'field' => 'hits', 'sort' => 'desc'),
array('data' => t('Url'), 'field' => 'url'),
array('data' => t('Last visit'), 'field' => 'last'),
);
$query .= tablesort_sql($header);
Index: modules/system/system.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.install,v
retrieving revision 1.312
diff -u -9 -p -r1.312 system.install
--- modules/system/system.install 17 Mar 2009 15:26:29 -0000 1.312
+++ modules/system/system.install 30 Mar 2009 21:32:25 -0000
@@ -3062,33 +3062,52 @@ function system_update_7011() {
'rid' => $rid,
'permission' => 'bypass node access',
));
}
$insert->execute();
return $ret;
}
/**
+ * Make tables case-sensitive on MySQL.
+ */
+function system_update_7012() {
+ $ret = array();
+ if (db_driver() == 'mysql') {
+ // Table names as used in D6. Some have changed and are no longer reported
+ // by hook_schema(). The list is generated using the following command:
+ // grep -r "^ \+\$schema\['[a-z_]\+'\] =" modules | cut -d\' -f2 | sort -u | xargs -I '*' echo -n "'*', "
+ $tables = array('access', 'accesslog', 'actions', 'actions_aid', 'aggregator_category', 'aggregator_category_feed', 'aggregator_category_item', 'aggregator_feed', 'aggregator_item', 'authmap', 'batch', 'blocks', 'blocks_roles', 'blogapi_files', 'book', 'book_temp', 'boxes', 'cache', 'cache_block', 'cache_filter', 'cache_form', 'cache_menu', 'cache_page', 'cache_update', 'comments', 'contact', 'files', 'filter_formats', 'filters', 'flood', 'forum', 'history', 'languages', 'locales_source', 'locales_target', 'menu_custom', 'menu_links', 'menu_router', 'node', 'node_access', 'node_comment_statistics', 'node_counter', 'node_revisions', 'node_type', 'openid_association', 'permission', 'poll', 'poll_choices', 'poll_votes', 'profile_fields', 'profile_values', 'role', 'search_dataset', 'search_index', 'search_node_links', 'search_total', 'sessions', 'system', 'term_data', 'term_hierarchy', 'term_node', 'term_relation', 'term_synonym', 'trigger_assignments', 'upload', 'url_alias', 'users', 'users_roles', 'variable', 'vocabulary', 'vocabulary_node_types', 'watchdog');
+ foreach ($tables as $table) {
+ if (db_table_exists($table)) {
+ $ret[] = update_sql('ALTER TABLE {' . $table . '} CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin');
+ }
+ }
+ }
+ return $ret;
+}
+
+/**
* Rename {blocks} table to {block}, {blocks_roles} to {block_role} and
* {boxes} to {box}.
*/
-function system_update_7012() {
+function system_update_7013() {
$ret = array();
db_rename_table($ret, 'blocks', 'block');
db_rename_table($ret, 'blocks_roles', 'block_role');
db_rename_table($ret, 'boxes', 'box');
return $ret;
}
/**
* Convert default time zone offset to default time zone name.
*/
-function system_update_7013() {
+function system_update_7014() {
$ret = array();
$timezone = NULL;
$timezones = system_time_zones();
// If the contributed Date module set a default time zone name, use this
// setting as the default time zone.
if (($timezone_name = variable_get('date_default_timezone_name')) && isset($timezones[$timezone_name])) {
$timezone = $timezone_name;
}
// If the contributed Event module has set a default site time zone, look up
@@ -3117,38 +3136,38 @@ function system_update_7013() {
}
variable_set('date_default_timezone', $timezone);
drupal_set_message('The default time zone has been set to ' . check_plain($timezone) . '. Please check the ' . l('date and time configuration page', 'admin/settings/regional-settings') . ' to configure it correctly.', 'warning');
return $ret;
}
/**
* Drop the bootstrap column from the {system} table.
*/
-function system_update_7014() {
+function system_update_7015() {
$ret = array();
db_drop_field($ret, 'system', 'bootstrap');
return $ret;
}
/**
* Change the user logout path.
*/
-function system_update_7015() {
+function system_update_7016() {
$ret = array();
$ret[] = update_sql("UPDATE {menu_links} SET link_path = 'user/logout' WHERE link_path = 'logout'");
$ret[] = update_sql("UPDATE {menu_links} SET router_path = 'user/logout' WHERE router_path = 'logout'");
return $ret;
}
/**
* Remove custom datatype *_unsigned in PostgreSQL.
*/
-function system_update_7016() {
+function system_update_7017() {
$ret = array();
// Only run these queries if the driver used is pgsql.
if (db_driver() == 'pgsql') {
$result = db_query("SELECT c.relname AS table, a.attname AS field,
pg_catalog.format_type(a.atttypid, a.atttypmod) AS type
FROM pg_catalog.pg_attribute a
LEFT JOIN pg_class c ON (c.oid = a.attrelid)
WHERE pg_catalog.pg_table_is_visible(c.oid) AND c.relkind = 'r'
AND pg_catalog.format_type(a.atttypid, a.atttypmod) LIKE '%unsigned%'");
@@ -3170,19 +3189,19 @@ function system_update_7016() {
$ret[] = update_sql('DROP DOMAIN int_unsigned');
$ret[] = update_sql('DROP DOMAIN bigint_unsigned');
}
return $ret;
}
/**
* Change the theme setting 'toggle_node_info' into a per content type variable.
*/
-function system_update_7017() {
+function system_update_7018() {
$ret = array();
$types = node_get_types();
if (count($types)) {
foreach ($types as $type) {
$node_info = theme_get_setting('toggle_node_info_' . $type->type);
if ($node_info !== NULL) {
variable_set('node_submitted_' . $type->type, $node_info);
$ret[] = array('success' => TRUE, 'query' => "variable_set('node_submitted_$type->type')");
}
@@ -3199,42 +3218,42 @@ function system_update_7017() {
variable_set('theme_settings', $theme_settings);
$ret[] = array('success' => TRUE, 'query' => "variable_set('theme_settings')");
return $ret;
}
/**
* Replace src index on the {url_alias} table with src, language.
*/
-function system_update_7018() {
+function system_update_7019() {
$ret = array();
db_add_index($ret, 'url_alias', 'src_language', array('src', 'language'));
db_drop_index($ret, 'url_alias', 'src');
return $ret;
}
/**
* Shorten the {system}.type column and add an index on type and name.
*/
-function system_update_7019() {
+function system_update_7020() {
$ret = array();
db_drop_index($ret, 'system', 'modules');
db_change_field($ret, 'system', 'type', 'type', array('type' => 'varchar', 'length' => 12, 'not null' => TRUE, 'default' => ''));
db_add_index($ret, 'system', 'modules', array('type', 'status', 'weight', 'filename'));
db_add_index($ret, 'system', 'type_name', array('type', 'name'));
return $ret;
}
/**
* Enable field module.
*/
-function system_update_7020() {
+function system_update_7021() {
$ret = array();
$module_list = array('field_sql_storage', 'field');
drupal_install_modules($module_list);
module_enable($module_list);
return $ret;
}
/**
* @} End of "defgroup updates-6.x-to-7.x"
Index: modules/user/user.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.module,v
retrieving revision 1.972
diff -u -9 -p -r1.972 user.module
--- modules/user/user.module 26 Mar 2009 13:31:28 -0000 1.972
+++ modules/user/user.module 30 Mar 2009 21:32:25 -0000
@@ -210,26 +210,24 @@ function user_load_multiple($uids = arra
if ($uids || ($conditions && !$passed_uids)) {
$query = db_select('users', 'u')->fields('u');
// If the $uids array is populated, add those to the query.
if ($uids) {
$query->condition('u.uid', $uids, 'IN');
}
// If the conditions array is populated, add those to the query.
if ($conditions) {
- // TODO D7: Using LIKE() to get a case insensitive comparison because Crell
- // and chx promise that dbtng will map it to ILIKE in postgres.
if (isset($conditions['name'])) {
- $query->condition('u.name', $conditions['name'], 'LIKE');
+ $query->where('LOWER(u.name) = LOWER(:name)', array(':name' => $conditions['name']));
unset($conditions['name']);
}
if (isset($conditions['mail'])) {
- $query->condition('u.mail', $conditions['mail'], 'LIKE');
+ $query->where('LOWER(u.mail) = LOWER(:mail)', array(':mail' => $conditions['mail']));
unset($conditions['mail']);
}
foreach ($conditions as $field => $value) {
$query->condition('u.' . $field, $value);
}
}
$result = $query->execute();
$queried_users = array();