提交 7a26b926 authored 作者: Thomas Mueller's avatar Thomas Mueller

LIKE: the escape mechanism can now be disable using ESCAPE ''.

The default escape character can be changed using the system property h2.defaultEscape.
上级 180480ee
......@@ -1344,11 +1344,16 @@ compare { {{ALL|ANY|SOME}(select)} | operand }
| [NOT] LIKE operand [ESCAPE string]
| [NOT] REGEXP operand
","
The right hand side of a condition. When comparing with LIKE, the wildcards
characters are _ (any one character) and % (any characters). The database uses
an index when comparing with LIKE except if the operand starts with a wildcard.
When comparing with REGEXP, regular expression matching is used. See Java
Matcher.find for details.
The right hand side of a condition.
When comparing with LIKE, the wildcards characters are _ (any one character)
and % (any characters). The database uses an index when comparing with LIKE
except if the operand starts with a wildcard. To search for the characters % and
_, the characters need to be escaped. The default escape character is \ (backslash).
To select no escape character, use ESCAPE '' (empty string).
When comparing with REGEXP, regular expression matching is used.
See Java Matcher.find for details.
","
LIKE 'Jo%'
"
......
......@@ -18,7 +18,10 @@ Change Log
<h1>Change Log</h1>
<h2>Next Version (unreleased)</h2>
<ul><li>Views using functions were not re-evaluated when necessary.
<ul><li>LIKE: the escape mechanism can now be disable using ESCAPE ''.
The default escape character can be changed using the system property h2.defaultEscape.
The default is still '\' (as in MySQL and PostgreSQL).
</li><li>Views using functions were not re-evaluated when necessary.
</li><li>Improved MySQL compatibility for SHOW COLUMNS.
</li><li>Improved PostgreSQL compatibility for timestamp literals with timezone.
</li><li>Sergi Vladykin translated the error messages to Russian. Thanks a lot!
......
......@@ -438,6 +438,7 @@ See also <a href="build.html#providing_patches">Providing Patches</a>.
</li><li>Support =ANY(array) as in PostgreSQL.
</li><li>IBM DB2 compatibility: support PREVIOUS VALUE FOR sequence.
</li><li>MySQL compatibility: alter table add index i(c), add constraint c foreign key(c) references t(c);
</li><li>Compatibility: use different LIKE ESCAPE characters depending on the mode (disable for Derby, HSQLDB, DB2, Oracle).
</li></ul>
<h2>Not Planned</h2>
......
......@@ -48,7 +48,7 @@ public class CreateUser extends DefineCommand {
}
private char[] getCharArray(Expression e) throws SQLException {
return e.getValue(session).getString().toCharArray();
return e.optimize(session).getValue(session).getString().toCharArray();
}
private byte[] getByteArray(Expression e) throws SQLException {
......@@ -74,11 +74,13 @@ public class CreateUser extends DefineCommand {
user.setComment(comment);
if (hash != null && salt != null) {
user.setSaltAndHash(getByteArray(salt), getByteArray(hash));
} else {
} else if (password != null) {
SHA256 sha = new SHA256();
char[] passwordChars = getCharArray(password);
byte[] userPasswordHash = sha.getKeyPasswordHash(userName, passwordChars);
user.setUserPasswordHash(userPasswordHash);
} else {
throw Message.throwInternalError();
}
db.addDatabaseObject(session, user);
return 0;
......
......@@ -179,6 +179,13 @@ public class SysProperties {
*/
public static final String CLIENT_TRACE_DIRECTORY = getStringSetting("h2.clientTraceDirectory", "trace.db/");
/**
* System property <code>h2.defaultEscape</code> (default: \).<br />
* The default escape character for LIKE comparisons. To select no escape
* character, use an empty string.
*/
public static final Character DEFAULT_ESCAPE_CHAR = getEscapeChar(getStringSetting("h2.defaultEscape", "\\"));
/**
* System property <code>h2.defaultMaxOperationMemory</code> (default:
* 100000).<br />
......@@ -730,4 +737,8 @@ public class SysProperties {
return getBooleanSetting(H2_PAGE_STORE, false);
}
private static Character getEscapeChar(String s) {
return s == null || s.length() == 0 ? null : s.charAt(0);
}
}
......@@ -147,11 +147,6 @@ public class Constants {
*/
public static final int DEFAULT_DATA_PAGE_SIZE = 512;
/**
* The default escape character for LIKE comparisons.
*/
public static final char DEFAULT_ESCAPE_CHAR = '\\';
/**
* If the HTTP server should allow connections from other computers by
* default.
......
......@@ -11,7 +11,7 @@ import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import org.h2.constant.ErrorCode;
import org.h2.engine.Constants;
import org.h2.constant.SysProperties;
import org.h2.engine.Session;
import org.h2.index.IndexCondition;
import org.h2.message.Message;
......@@ -112,14 +112,16 @@ public class CompareLike extends Condition {
return this;
}
private char getEscapeChar(Value e) {
private Character getEscapeChar(Value e) {
if (e == null) {
return Constants.DEFAULT_ESCAPE_CHAR;
return SysProperties.DEFAULT_ESCAPE_CHAR;
}
String es = e.getString();
char esc;
if (es == null || es.length() == 0) {
esc = Constants.DEFAULT_ESCAPE_CHAR;
Character esc;
if (es == null) {
esc = SysProperties.DEFAULT_ESCAPE_CHAR;
} else if (es.length() == 0) {
esc = null;
} else {
esc = es.charAt(0);
}
......@@ -274,7 +276,7 @@ public class CompareLike extends Condition {
return compareAt(value, 0, 0, value.length());
}
private void initPattern(String p, char escapeChar) throws SQLException {
private void initPattern(String p, Character escape) throws SQLException {
if (regexp) {
patternString = p;
try {
......@@ -301,12 +303,12 @@ public class CompareLike extends Condition {
for (int i = 0; i < len; i++) {
char c = p.charAt(i);
int type;
if (escapeChar == c) {
if (escape != null && escape == c) {
if (i >= len - 1) {
throw Message.getSQLException(ErrorCode.LIKE_ESCAPE_ERROR_1, StringUtils.addAsterisk(p, i));
}
c = p.charAt(++i);
if (c != '_' && c != '%' && c != escapeChar) {
if (c != '_' && c != '%' && c != escape) {
throw Message.getSQLException(ErrorCode.LIKE_ESCAPE_ERROR_1, StringUtils.addAsterisk(p, i));
}
type = MATCH;
......
......@@ -155,9 +155,9 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
+ "TYPE_NAME REF_GENERATION, "
+ "SQL "
+ "FROM INFORMATION_SCHEMA.TABLES "
+ "WHERE TABLE_CATALOG LIKE ? "
+ "AND TABLE_SCHEMA LIKE ? "
+ "AND TABLE_NAME LIKE ? "
+ "WHERE TABLE_CATALOG LIKE ? ESCAPE '\\' "
+ "AND TABLE_SCHEMA LIKE ? ESCAPE '\\' "
+ "AND TABLE_NAME LIKE ? ESCAPE '\\' "
+ "AND (" + tableType + ") "
+ "ORDER BY TABLE_TYPE, TABLE_SCHEMA, TABLE_NAME");
prep.setString(1, getCatalogPattern(catalogPattern));
......@@ -248,10 +248,10 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
+ "SOURCE_DATA_TYPE, "
+ "CASE WHEN SEQUENCE_NAME IS NULL THEN 'NO' ELSE 'YES' END IS_AUTOINCREMENT "
+ "FROM INFORMATION_SCHEMA.COLUMNS "
+ "WHERE TABLE_CATALOG LIKE ? "
+ "AND TABLE_SCHEMA LIKE ? "
+ "AND TABLE_NAME LIKE ? "
+ "AND COLUMN_NAME LIKE ? "
+ "WHERE TABLE_CATALOG LIKE ? ESCAPE '\\' "
+ "AND TABLE_SCHEMA LIKE ? ESCAPE '\\' "
+ "AND TABLE_NAME LIKE ? ESCAPE '\\' "
+ "AND COLUMN_NAME LIKE ? ESCAPE '\\' "
+ "ORDER BY TABLE_SCHEM, TABLE_NAME, ORDINAL_POSITION");
prep.setString(1, getCatalogPattern(catalogPattern));
prep.setString(2, getSchemaPattern(schemaPattern));
......@@ -327,8 +327,8 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
+ "FILTER_CONDITION, "
+ "SORT_TYPE "
+ "FROM INFORMATION_SCHEMA.INDEXES "
+ "WHERE TABLE_CATALOG LIKE ? "
+ "AND TABLE_SCHEMA LIKE ? "
+ "WHERE TABLE_CATALOG LIKE ? ESCAPE '\\' "
+ "AND TABLE_SCHEMA LIKE ? ESCAPE '\\' "
+ "AND (" + uniqueCondition + ") "
+ "AND TABLE_NAME = ? "
+ "ORDER BY NON_UNIQUE, TYPE, TABLE_SCHEM, INDEX_NAME, ORDINAL_POSITION");
......@@ -377,8 +377,8 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
+ "ORDINAL_POSITION KEY_SEQ, "
+ "IFNULL(CONSTRAINT_NAME, INDEX_NAME) PK_NAME "
+ "FROM INFORMATION_SCHEMA.INDEXES "
+ "WHERE TABLE_CATALOG LIKE ? "
+ "AND TABLE_SCHEMA LIKE ? "
+ "WHERE TABLE_CATALOG LIKE ? ESCAPE '\\' "
+ "AND TABLE_SCHEMA LIKE ? ESCAPE '\\' "
+ "AND TABLE_NAME = ? "
+ "AND PRIMARY_KEY = TRUE "
+ "ORDER BY COLUMN_NAME");
......@@ -554,9 +554,9 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
+ "RETURNS_RESULT PROCEDURE_TYPE, "
+ "ALIAS_NAME SPECIFIC_NAME "
+ "FROM INFORMATION_SCHEMA.FUNCTION_ALIASES "
+ "WHERE ALIAS_CATALOG LIKE ? "
+ "AND ALIAS_SCHEMA LIKE ? "
+ "AND ALIAS_NAME LIKE ? "
+ "WHERE ALIAS_CATALOG LIKE ? ESCAPE '\\' "
+ "AND ALIAS_SCHEMA LIKE ? ESCAPE '\\' "
+ "AND ALIAS_NAME LIKE ? ESCAPE '\\' "
+ "ORDER BY PROCEDURE_SCHEM, PROCEDURE_NAME, NUM_INPUT_PARAMS");
prep.setString(1, getCatalogPattern(catalogPattern));
prep.setString(2, getSchemaPattern(schemaPattern));
......@@ -638,10 +638,10 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
+ "'YES' IS_NULLABLE, "
+ "ALIAS_NAME SPECIFIC_NAME "
+ "FROM INFORMATION_SCHEMA.FUNCTION_COLUMNS "
+ "WHERE ALIAS_CATALOG LIKE ? "
+ "AND ALIAS_SCHEMA LIKE ? "
+ "AND ALIAS_NAME LIKE ? "
+ "AND COLUMN_NAME LIKE ? "
+ "WHERE ALIAS_CATALOG LIKE ? ESCAPE '\\' "
+ "AND ALIAS_SCHEMA LIKE ? ESCAPE '\\' "
+ "AND ALIAS_NAME LIKE ? ESCAPE '\\' "
+ "AND COLUMN_NAME LIKE ? ESCAPE '\\' "
+ "ORDER BY PROCEDURE_SCHEM, PROCEDURE_NAME, ORDINAL_POSITION");
prep.setString(1, getCatalogPattern(catalogPattern));
prep.setString(2, getSchemaPattern(schemaPattern));
......@@ -780,10 +780,10 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
+ "PRIVILEGE_TYPE PRIVILEGE, "
+ "IS_GRANTABLE "
+ "FROM INFORMATION_SCHEMA.COLUMN_PRIVILEGES "
+ "WHERE TABLE_CATALOG LIKE ? "
+ "AND TABLE_SCHEMA LIKE ? "
+ "WHERE TABLE_CATALOG LIKE ? ESCAPE '\\' "
+ "AND TABLE_SCHEMA LIKE ? ESCAPE '\\' "
+ "AND TABLE_NAME = ? "
+ "AND COLUMN_NAME LIKE ? "
+ "AND COLUMN_NAME LIKE ? ESCAPE '\\' "
+ "ORDER BY COLUMN_NAME, PRIVILEGE");
prep.setString(1, getCatalogPattern(catalogPattern));
prep.setString(2, getSchemaPattern(schemaPattern));
......@@ -837,9 +837,9 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
+ "PRIVILEGE_TYPE PRIVILEGE, "
+ "IS_GRANTABLE "
+ "FROM INFORMATION_SCHEMA.TABLE_PRIVILEGES "
+ "WHERE TABLE_CATALOG LIKE ? "
+ "AND TABLE_SCHEMA LIKE ? "
+ "AND TABLE_NAME LIKE ? "
+ "WHERE TABLE_CATALOG LIKE ? ESCAPE '\\' "
+ "AND TABLE_SCHEMA LIKE ? ESCAPE '\\' "
+ "AND TABLE_NAME LIKE ? ESCAPE '\\' "
+ "ORDER BY TABLE_SCHEM, TABLE_NAME, PRIVILEGE");
prep.setString(1, getCatalogPattern(catalogPattern));
prep.setString(2, getSchemaPattern(schemaPattern));
......@@ -897,8 +897,8 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
+" INFORMATION_SCHEMA.COLUMNS C "
+ "WHERE C.TABLE_NAME = I.TABLE_NAME "
+ "AND C.COLUMN_NAME = I.COLUMN_NAME "
+ "AND C.TABLE_CATALOG LIKE ? "
+ "AND C.TABLE_SCHEMA LIKE ? "
+ "AND C.TABLE_CATALOG LIKE ? ESCAPE '\\' "
+ "AND C.TABLE_SCHEMA LIKE ? ESCAPE '\\' "
+ "AND C.TABLE_NAME = ? "
+ "AND I.PRIMARY_KEY = TRUE "
+ "ORDER BY SCOPE");
......@@ -1019,8 +1019,8 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
+ "PK_NAME, "
+ "DEFERRABILITY "
+ "FROM INFORMATION_SCHEMA.CROSS_REFERENCES "
+ "WHERE FKTABLE_CATALOG LIKE ? "
+ "AND FKTABLE_SCHEMA LIKE ? "
+ "WHERE FKTABLE_CATALOG LIKE ? ESCAPE '\\' "
+ "AND FKTABLE_SCHEMA LIKE ? ESCAPE '\\' "
+ "AND FKTABLE_NAME = ? "
+ "ORDER BY PKTABLE_CAT, PKTABLE_SCHEM, PKTABLE_NAME, FK_NAME, KEY_SEQ");
prep.setString(1, getCatalogPattern(catalogPattern));
......@@ -1089,8 +1089,8 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
+ "PK_NAME, "
+ "DEFERRABILITY "
+ "FROM INFORMATION_SCHEMA.CROSS_REFERENCES "
+ "WHERE PKTABLE_CATALOG LIKE ? "
+ "AND PKTABLE_SCHEMA LIKE ? "
+ "WHERE PKTABLE_CATALOG LIKE ? ESCAPE '\\' "
+ "AND PKTABLE_SCHEMA LIKE ? ESCAPE '\\' "
+ "AND PKTABLE_NAME = ? "
+ "ORDER BY FKTABLE_CAT, FKTABLE_SCHEM, FKTABLE_NAME, FK_NAME, KEY_SEQ");
prep.setString(1, getCatalogPattern(catalogPattern));
......@@ -1169,11 +1169,11 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
+ "PK_NAME, "
+ "DEFERRABILITY "
+ "FROM INFORMATION_SCHEMA.CROSS_REFERENCES "
+ "WHERE PKTABLE_CATALOG LIKE ? "
+ "AND PKTABLE_SCHEMA LIKE ? "
+ "WHERE PKTABLE_CATALOG LIKE ? ESCAPE '\\' "
+ "AND PKTABLE_SCHEMA LIKE ? ESCAPE '\\' "
+ "AND PKTABLE_NAME = ? "
+ "AND FKTABLE_CATALOG LIKE ? "
+ "AND FKTABLE_SCHEMA LIKE ? "
+ "AND FKTABLE_CATALOG LIKE ? ESCAPE '\\' "
+ "AND FKTABLE_SCHEMA LIKE ? ESCAPE '\\' "
+ "AND FKTABLE_NAME = ? "
+ "ORDER BY FKTABLE_CAT, FKTABLE_SCHEM, FKTABLE_NAME, FK_NAME, KEY_SEQ");
prep.setString(1, getCatalogPattern(primaryCatalogPattern));
......@@ -1421,13 +1421,15 @@ public class JdbcDatabaseMetaData extends TraceObject implements DatabaseMetaDat
}
/**
* Returns the default escape character for LIKE.
* Returns the default escape character for DatabaseMetaData search
* patterns.
*
* @return the character '\'
* @return the default escape character (always '\', independent on the
* mode)
*/
public String getSearchStringEscape() {
debugCodeCall("getSearchStringEscape");
return "" + Constants.DEFAULT_ESCAPE_CHAR;
return "\\";
}
/**
......
......@@ -295,15 +295,6 @@ java org.h2.test.TestAll timer
/*
LIKE: Use no default escape character, except for PostgreSQL and MySQL compatibility
See DatabaseMetaData.getSearchStringEscape
PostgreSQL: select no escape character by writing ESCAPE ''
drop table test;
create table test(id int);
insert into test values(1);
select * from test where '\' like '\' escape '';
select * from test where '\' like '\';
page store: TestBtreeIndex
better document that ddl statements commit
......@@ -355,10 +346,10 @@ kill -9 `jps -l | grep "org.h2.test.TestAll" | cut -d " " -f 1`
test.runTests();
TestPerformance.main(new String[]{ "-init", "-db", "1"});
// System.setProperty(SysProperties.H2_PAGE_STORE, "false");
// test.pageStore = false;
// test.runTests();
// TestPerformance.main(new String[]{ "-init", "-db", "1"});
System.setProperty(SysProperties.H2_PAGE_STORE, "false");
test.pageStore = false;
test.runTests();
TestPerformance.main(new String[]{ "-init", "-db", "1"});
}
System.out.println(TestBase.formatTime(System.currentTimeMillis() - time) + " total");
}
......
select 1 from dual where '\' like '\' escape '';
> 1;
select left(timestamp '2001-02-03 08:20:31+04', 4);
> 2001;
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论