Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
project
drupal
Commits
82c20e66
Commit
82c20e66
authored
Dec 13, 2009
by
Angie Byron
Browse files
#654662
by c960657 and Crell: Allow escaping wildcard characters in LIKE queries.
parent
e5356ea6
Changes
4
Hide whitespace changes
Inline
Side-by-side
includes/database/database.inc
View file @
82c20e66
...
...
@@ -819,6 +819,34 @@ public function escapeTable($table) {
return
preg_replace
(
'/[^A-Za-z0-9_]+/'
,
''
,
$table
);
}
/**
* Escape characters that work as wildcard characters in a LIKE pattern.
*
* The wildcard characters "%" and "_" as well as backslash are prefixed with
* a backslash. Use this to do a seach for a verbatim string without any
* wildcard behavior.
*
* For example, the following does a case-insensitive query for all rows whose
* name starts with $prefix:
* @code
* $result = db_query(
* 'SELECT * FROM person WHERE name LIKE :pattern',
* array(':pattern' => db_like($prefix) . '%')
* );
* @endcode
*
* Backslash is defined as escape character for LIKE patterns in
* DatabaseCondition::mapConditionOperator().
*
* @param $string
* The string to escape.
* @return
* The escaped string.
*/
public
function
escapeLike
(
$string
)
{
return
addcslashes
(
$string
,
'\%_'
);
}
/**
* Determine if there is an active transaction open.
*
...
...
@@ -2234,6 +2262,34 @@ function db_escape_table($table) {
return
Database
::
getConnection
()
->
escapeTable
(
$table
);
}
/**
* Escape characters that work as wildcard characters in a LIKE pattern.
*
* The wildcard characters "%" and "_" as well as backslash are prefixed with
* a backslash. Use this to do a seach for a verbatim string without any
* wildcard behavior.
*
* For example, the following does a case-insensitive query for all rows whose
* name starts with $prefix:
* @code
* $result = db_query(
* 'SELECT * FROM person WHERE name LIKE :pattern',
* array(':pattern' => db_like($prefix) . '%')
* );
* @endcode
*
* Backslash is defined as escape character for LIKE patterns in
* DatabaseCondition::mapConditionOperator().
*
* @param $string
* The string to escape.
* @return
* The escaped string.
*/
function
db_like
(
$string
)
{
return
Database
::
getConnection
()
->
escapeLike
(
$string
);
}
/**
* Retrieve the name of the currently active database driver, such as
* "mysql" or "pgsql".
...
...
includes/database/pgsql/database.inc
View file @
82c20e66
...
...
@@ -120,8 +120,9 @@ public function databaseType() {
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'
),
// statements, we need to use ILIKE instead. Use backslash for escaping
// wildcard characters.
'LIKE'
=>
array
(
'operator'
=>
'ILIKE'
,
'postfix'
=>
" ESCAPE '
\\\\
'"
),
);
return
isset
(
$specials
[
$operator
])
?
$specials
[
$operator
]
:
NULL
;
...
...
includes/database/query.inc
View file @
82c20e66
...
...
@@ -1330,13 +1330,14 @@ protected function mapConditionOperator($operator) {
'NOT IN'
=>
array
(
'delimiter'
=>
', '
,
'prefix'
=>
' ('
,
'postfix'
=>
')'
),
'IS NULL'
=>
array
(
'use_value'
=>
FALSE
),
'IS NOT NULL'
=>
array
(
'use_value'
=>
FALSE
),
// Use backslash for escaping wildcard characters.
'LIKE'
=>
array
(
'postfix'
=>
" ESCAPE '
\\\\
'"
),
// These ones are here for performance reasons.
'='
=>
array
(),
'<'
=>
array
(),
'>'
=>
array
(),
'>='
=>
array
(),
'<='
=>
array
(),
'LIKE'
=>
array
(),
);
if
(
isset
(
$specials
[
$operator
]))
{
$return
=
$specials
[
$operator
];
...
...
modules/simpletest/tests/database_test.test
View file @
82c20e66
...
...
@@ -2643,6 +2643,63 @@ class DatabaseAnsiSyntaxTestCase extends DatabaseTestCase {
));
$this
->
assertIdentical
(
$result
->
fetchField
(),
'The age of John is 25.'
,
t
(
'Field ANSI Concat works.'
));
}
/**
* Test escaping of LIKE wildcards.
*/
function
testLikeEscape
()
{
db_insert
(
'test'
)
->
fields
(
array
(
'name'
=>
'Ring_'
,
))
->
execute
();
// Match both "Ringo" and "Ring_".
$num_matches
=
db_select
(
'test'
,
't'
)
->
condition
(
'name'
,
'Ring_'
,
'LIKE'
)
->
countQuery
()
->
execute
()
->
fetchField
();
$this
->
assertIdentical
(
$num_matches
,
'2'
,
t
(
'Found 2 records.'
));
// Match only "Ring_" using a LIKE expression with no wildcards.
$num_matches
=
db_select
(
'test'
,
't'
)
->
condition
(
'name'
,
db_like
(
'Ring_'
),
'LIKE'
)
->
countQuery
()
->
execute
()
->
fetchField
();
$this
->
assertIdentical
(
$num_matches
,
'1'
,
t
(
'Found 1 record.'
));
}
/**
* Test LIKE query containing a backslash.
*/
function
testLikeBackslash
()
{
db_insert
(
'test'
)
->
fields
(
array
(
'name'
))
->
values
(
array
(
'name'
=>
'abcde\f'
,
))
->
values
(
array
(
'name'
=>
'abc%\_'
,
))
->
execute
();
// Match both rows using a LIKE expression with two wildcards and a verbatim
// backslash.
$num_matches
=
db_select
(
'test'
,
't'
)
->
condition
(
'name'
,
'abc%\\\\_'
,
'LIKE'
)
->
countQuery
()
->
execute
()
->
fetchField
();
$this
->
assertIdentical
(
$num_matches
,
'2'
,
t
(
'Found 2 records.'
));
// Match only the former using a LIKE expression with no wildcards.
$num_matches
=
db_select
(
'test'
,
't'
)
->
condition
(
'name'
,
db_like
(
'abc%\_'
),
'LIKE'
)
->
countQuery
()
->
execute
()
->
fetchField
();
$this
->
assertIdentical
(
$num_matches
,
'1'
,
t
(
'Found 1 record.'
));
}
}
/**
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment