Unverified 提交 1edf2411 authored 作者: Noel Grandin's avatar Noel Grandin 提交者: GitHub

Merge pull request #789 from katzyn/OracleDate

Map DATE in Oracle mode to ValueTimestamp
...@@ -95,6 +95,7 @@ import org.h2.engine.Constants; ...@@ -95,6 +95,7 @@ import org.h2.engine.Constants;
import org.h2.engine.Database; import org.h2.engine.Database;
import org.h2.engine.DbObject; import org.h2.engine.DbObject;
import org.h2.engine.FunctionAlias; import org.h2.engine.FunctionAlias;
import org.h2.engine.Mode;
import org.h2.engine.Mode.ModeEnum; import org.h2.engine.Mode.ModeEnum;
import org.h2.engine.Procedure; import org.h2.engine.Procedure;
import org.h2.engine.Right; import org.h2.engine.Right;
...@@ -3144,7 +3145,7 @@ public class Parser { ...@@ -3144,7 +3145,7 @@ public class Parser {
String timestamp = currentValue.getString(); String timestamp = currentValue.getString();
read(); read();
r = ValueExpression r = ValueExpression
.get(ValueTimestamp.parse(timestamp, session.getDatabase().getMode())); .get(ValueTimestamp.parse(timestamp, database.getMode()));
} else if (equalsToken("X", name)) { } else if (equalsToken("X", name)) {
read(); read();
byte[] buffer = StringUtils byte[] buffer = StringUtils
...@@ -4272,7 +4273,7 @@ public class Parser { ...@@ -4272,7 +4273,7 @@ public class Parser {
boolean isIdentity = readIf("IDENTITY"); boolean isIdentity = readIf("IDENTITY");
if (isIdentity || readIf("BIGSERIAL")) { if (isIdentity || readIf("BIGSERIAL")) {
// Check if any of them are disallowed in the current Mode // Check if any of them are disallowed in the current Mode
if (isIdentity && session.getDatabase().getMode(). if (isIdentity && database.getMode().
disallowedTypes.contains("IDENTITY")) { disallowedTypes.contains("IDENTITY")) {
throw DbException.get(ErrorCode.UNKNOWN_DATA_TYPE_1, throw DbException.get(ErrorCode.UNKNOWN_DATA_TYPE_1,
currentToken); currentToken);
...@@ -4448,8 +4449,9 @@ public class Parser { ...@@ -4448,8 +4449,9 @@ public class Parser {
scale = templateColumn.getScale(); scale = templateColumn.getScale();
enumerators = templateColumn.getEnumerators(); enumerators = templateColumn.getEnumerators();
} else { } else {
dataType = DataType.getTypeByName(original); Mode mode = database.getMode();
if (dataType == null || session.getDatabase().getMode().disallowedTypes.contains(original)) { dataType = DataType.getTypeByName(original, mode);
if (dataType == null || mode.disallowedTypes.contains(original)) {
throw DbException.get(ErrorCode.UNKNOWN_DATA_TYPE_1, throw DbException.get(ErrorCode.UNKNOWN_DATA_TYPE_1,
currentToken); currentToken);
} }
...@@ -4457,7 +4459,7 @@ public class Parser { ...@@ -4457,7 +4459,7 @@ public class Parser {
if (database.getIgnoreCase() && dataType.type == Value.STRING && if (database.getIgnoreCase() && dataType.type == Value.STRING &&
!equalsToken("VARCHAR_CASESENSITIVE", original)) { !equalsToken("VARCHAR_CASESENSITIVE", original)) {
original = "VARCHAR_IGNORECASE"; original = "VARCHAR_IGNORECASE";
dataType = DataType.getTypeByName(original); dataType = DataType.getTypeByName(original, database.getMode());
} }
if (regular) { if (regular) {
read(); read();
...@@ -4536,7 +4538,7 @@ public class Parser { ...@@ -4536,7 +4538,7 @@ public class Parser {
read("BIT"); read("BIT");
read("DATA"); read("DATA");
if (dataType.type == Value.STRING) { if (dataType.type == Value.STRING) {
dataType = DataType.getTypeByName("BINARY"); dataType = DataType.getTypeByName("BINARY", database.getMode());
} }
} }
// MySQL compatibility // MySQL compatibility
...@@ -5220,7 +5222,7 @@ public class Parser { ...@@ -5220,7 +5222,7 @@ public class Parser {
Table recursiveTable = null; Table recursiveTable = null;
ArrayList<Column> columns = New.arrayList(); ArrayList<Column> columns = New.arrayList();
String[] cols = null; String[] cols = null;
Database db = session.getDatabase(); Database db = database;
// column names are now optional - they can be inferred from the named // column names are now optional - they can be inferred from the named
// query, if not supplied by user // query, if not supplied by user
...@@ -5252,7 +5254,7 @@ public class Parser { ...@@ -5252,7 +5254,7 @@ public class Parser {
} }
if (isPersistent) { if (isPersistent) {
oldViewFound.lock(session, true, true); oldViewFound.lock(session, true, true);
session.getDatabase().removeSchemaObject(session, oldViewFound); database.removeSchemaObject(session, oldViewFound);
} else { } else {
session.removeLocalTempTable(oldViewFound); session.removeLocalTempTable(oldViewFound);
...@@ -6417,7 +6419,7 @@ public class Parser { ...@@ -6417,7 +6419,7 @@ public class Parser {
// need to read ahead, as it could be a column name // need to read ahead, as it could be a column name
int start = lastParseIndex; int start = lastParseIndex;
read(); read();
if (DataType.getTypeByName(currentToken) != null) { if (DataType.getTypeByName(currentToken, database.getMode()) != null) {
// known data type // known data type
parseIndex = start; parseIndex = start;
read(); read();
......
...@@ -55,7 +55,7 @@ public class CreateUserDataType extends DefineCommand { ...@@ -55,7 +55,7 @@ public class CreateUserDataType extends DefineCommand {
ErrorCode.USER_DATA_TYPE_ALREADY_EXISTS_1, ErrorCode.USER_DATA_TYPE_ALREADY_EXISTS_1,
typeName); typeName);
} }
DataType builtIn = DataType.getTypeByName(typeName); DataType builtIn = DataType.getTypeByName(typeName, session.getDatabase().getMode());
if (builtIn != null) { if (builtIn != null) {
if (!builtIn.hidden) { if (!builtIn.hidden) {
throw DbException.get( throw DbException.get(
......
...@@ -10,6 +10,8 @@ import java.util.HashMap; ...@@ -10,6 +10,8 @@ import java.util.HashMap;
import java.util.Set; import java.util.Set;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
import org.h2.value.DataType;
import org.h2.value.Value;
/** /**
* The compatibility modes. There is a fixed set of modes (for example * The compatibility modes. There is a fixed set of modes (for example
...@@ -198,6 +200,11 @@ public class Mode { ...@@ -198,6 +200,11 @@ public class Mode {
*/ */
public Set<String> disallowedTypes = Collections.emptySet(); public Set<String> disallowedTypes = Collections.emptySet();
/**
* Custom mappings from type names to data types.
*/
public HashMap<String, DataType> typeByNameMap = new HashMap<>();
private final String name; private final String name;
private ModeEnum modeEnum; private ModeEnum modeEnum;
...@@ -285,6 +292,7 @@ public class Mode { ...@@ -285,6 +292,7 @@ public class Mode {
mode.supportedClientInfoPropertiesRegEx = mode.supportedClientInfoPropertiesRegEx =
Pattern.compile(".*\\..*"); Pattern.compile(".*\\..*");
mode.prohibitEmptyInPredicate = true; mode.prohibitEmptyInPredicate = true;
mode.typeByNameMap.put("DATE", DataType.getDataType(Value.TIMESTAMP));
add(mode); add(mode);
mode = new Mode(ModeEnum.PostgreSQL.name()); mode = new Mode(ModeEnum.PostgreSQL.name());
......
...@@ -584,7 +584,7 @@ public class MetaTable extends Table { ...@@ -584,7 +584,7 @@ public class MetaTable extends Table {
Value.STRING_IGNORECASE : Value.STRING; Value.STRING_IGNORECASE : Value.STRING;
name = nameType; name = nameType;
} else { } else {
dataType = DataType.getTypeByName(nameType.substring(idx + 1)).type; dataType = DataType.getTypeByName(nameType.substring(idx + 1), database.getMode()).type;
name = nameType.substring(0, idx); name = nameType.substring(0, idx);
} }
cols[i] = new Column(name, dataType); cols[i] = new Column(name, dataType);
......
...@@ -26,6 +26,7 @@ import java.util.HashMap; ...@@ -26,6 +26,7 @@ import java.util.HashMap;
import java.util.UUID; import java.util.UUID;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.api.TimestampWithTimeZone; import org.h2.api.TimestampWithTimeZone;
import org.h2.engine.Mode;
import org.h2.engine.SessionInterface; import org.h2.engine.SessionInterface;
import org.h2.engine.SysProperties; import org.h2.engine.SysProperties;
import org.h2.jdbc.JdbcArray; import org.h2.jdbc.JdbcArray;
...@@ -1192,13 +1193,17 @@ public class DataType { ...@@ -1192,13 +1193,17 @@ public class DataType {
* Get a data type object from a type name. * Get a data type object from a type name.
* *
* @param s the type name * @param s the type name
* @param mode database mode
* @return the data type object * @return the data type object
*/ */
public static DataType getTypeByName(String s) { public static DataType getTypeByName(String s, Mode mode) {
DataType result = TYPES_BY_NAME.get(s); DataType result = mode.typeByNameMap.get(s);
if (result == null) {
result = TYPES_BY_NAME.get(s);
if (result == null && JdbcUtils.customDataTypesHandler != null) { if (result == null && JdbcUtils.customDataTypesHandler != null) {
result = JdbcUtils.customDataTypesHandler.getDataTypeByName(s); result = JdbcUtils.customDataTypesHandler.getDataTypeByName(s);
} }
}
return result; return result;
} }
......
...@@ -10,6 +10,7 @@ import java.sql.PreparedStatement; ...@@ -10,6 +10,7 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import java.sql.Timestamp;
import java.sql.Types; import java.sql.Types;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Arrays; import java.util.Arrays;
...@@ -41,6 +42,7 @@ public class TestCompatibilityOracle extends TestBase { ...@@ -41,6 +42,7 @@ public class TestCompatibilityOracle extends TestBase {
testToDate(); testToDate();
testForbidEmptyInClause(); testForbidEmptyInClause();
testSpecialTypes(); testSpecialTypes();
testDate();
} }
private void testNotNullSyntax() throws SQLException { private void testNotNullSyntax() throws SQLException {
...@@ -249,6 +251,38 @@ public class TestCompatibilityOracle extends TestBase { ...@@ -249,6 +251,38 @@ public class TestCompatibilityOracle extends TestBase {
} }
} }
private void testDate() throws SQLException {
deleteDb("oracle");
Connection conn = getConnection("oracle;MODE=Oracle");
Statement stat = conn.createStatement();
Timestamp t1 = Timestamp.valueOf("2011-02-03 12:11:10");
Timestamp t2 = Timestamp.valueOf("1999-10-15 13:14:15");
Timestamp t3 = Timestamp.valueOf("2030-11-22 11:22:33");
Timestamp t4 = Timestamp.valueOf("2018-01-10 22:10:01");
stat.execute("CREATE TABLE TEST (ID INT PRIMARY KEY, D DATE)");
stat.executeUpdate("INSERT INTO TEST VALUES(1, TIMESTAMP '2011-02-03 12:11:10')");
stat.executeUpdate("INSERT INTO TEST VALUES(2, CAST ('1999-10-15 13:14:15' AS DATE))");
stat.executeUpdate("INSERT INTO TEST VALUES(3, '2030-11-22 11:22:33')");
PreparedStatement ps = conn.prepareStatement("INSERT INTO TEST VALUES (?, ?)");
ps.setInt(1, 4);
ps.setTimestamp(2, t4);
ps.executeUpdate();
ResultSet rs = stat.executeQuery("SELECT D FROM TEST ORDER BY ID");
rs.next();
assertEquals(t1, rs.getTimestamp(1));
rs.next();
assertEquals(t2, rs.getTimestamp(1));
rs.next();
assertEquals(t3, rs.getTimestamp(1));
rs.next();
assertEquals(t4, rs.getTimestamp(1));
assertFalse(rs.next());
conn.close();
}
private void assertResultDate(String expected, Statement stat, String sql) private void assertResultDate(String expected, Statement stat, String sql)
throws SQLException { throws SQLException {
SimpleDateFormat iso8601 = new SimpleDateFormat( SimpleDateFormat iso8601 = new SimpleDateFormat(
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论