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;
import org.h2.engine.Database;
import org.h2.engine.DbObject;
import org.h2.engine.FunctionAlias;
import org.h2.engine.Mode;
import org.h2.engine.Mode.ModeEnum;
import org.h2.engine.Procedure;
import org.h2.engine.Right;
......@@ -3144,7 +3145,7 @@ public class Parser {
String timestamp = currentValue.getString();
read();
r = ValueExpression
.get(ValueTimestamp.parse(timestamp, session.getDatabase().getMode()));
.get(ValueTimestamp.parse(timestamp, database.getMode()));
} else if (equalsToken("X", name)) {
read();
byte[] buffer = StringUtils
......@@ -4272,7 +4273,7 @@ public class Parser {
boolean isIdentity = readIf("IDENTITY");
if (isIdentity || readIf("BIGSERIAL")) {
// Check if any of them are disallowed in the current Mode
if (isIdentity && session.getDatabase().getMode().
if (isIdentity && database.getMode().
disallowedTypes.contains("IDENTITY")) {
throw DbException.get(ErrorCode.UNKNOWN_DATA_TYPE_1,
currentToken);
......@@ -4448,8 +4449,9 @@ public class Parser {
scale = templateColumn.getScale();
enumerators = templateColumn.getEnumerators();
} else {
dataType = DataType.getTypeByName(original);
if (dataType == null || session.getDatabase().getMode().disallowedTypes.contains(original)) {
Mode mode = database.getMode();
dataType = DataType.getTypeByName(original, mode);
if (dataType == null || mode.disallowedTypes.contains(original)) {
throw DbException.get(ErrorCode.UNKNOWN_DATA_TYPE_1,
currentToken);
}
......@@ -4457,7 +4459,7 @@ public class Parser {
if (database.getIgnoreCase() && dataType.type == Value.STRING &&
!equalsToken("VARCHAR_CASESENSITIVE", original)) {
original = "VARCHAR_IGNORECASE";
dataType = DataType.getTypeByName(original);
dataType = DataType.getTypeByName(original, database.getMode());
}
if (regular) {
read();
......@@ -4536,7 +4538,7 @@ public class Parser {
read("BIT");
read("DATA");
if (dataType.type == Value.STRING) {
dataType = DataType.getTypeByName("BINARY");
dataType = DataType.getTypeByName("BINARY", database.getMode());
}
}
// MySQL compatibility
......@@ -5220,7 +5222,7 @@ public class Parser {
Table recursiveTable = null;
ArrayList<Column> columns = New.arrayList();
String[] cols = null;
Database db = session.getDatabase();
Database db = database;
// column names are now optional - they can be inferred from the named
// query, if not supplied by user
......@@ -5252,7 +5254,7 @@ public class Parser {
}
if (isPersistent) {
oldViewFound.lock(session, true, true);
session.getDatabase().removeSchemaObject(session, oldViewFound);
database.removeSchemaObject(session, oldViewFound);
} else {
session.removeLocalTempTable(oldViewFound);
......@@ -6417,7 +6419,7 @@ public class Parser {
// need to read ahead, as it could be a column name
int start = lastParseIndex;
read();
if (DataType.getTypeByName(currentToken) != null) {
if (DataType.getTypeByName(currentToken, database.getMode()) != null) {
// known data type
parseIndex = start;
read();
......
......@@ -55,7 +55,7 @@ public class CreateUserDataType extends DefineCommand {
ErrorCode.USER_DATA_TYPE_ALREADY_EXISTS_1,
typeName);
}
DataType builtIn = DataType.getTypeByName(typeName);
DataType builtIn = DataType.getTypeByName(typeName, session.getDatabase().getMode());
if (builtIn != null) {
if (!builtIn.hidden) {
throw DbException.get(
......
......@@ -10,6 +10,8 @@ import java.util.HashMap;
import java.util.Set;
import java.util.regex.Pattern;
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
......@@ -198,6 +200,11 @@ public class Mode {
*/
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 ModeEnum modeEnum;
......@@ -285,6 +292,7 @@ public class Mode {
mode.supportedClientInfoPropertiesRegEx =
Pattern.compile(".*\\..*");
mode.prohibitEmptyInPredicate = true;
mode.typeByNameMap.put("DATE", DataType.getDataType(Value.TIMESTAMP));
add(mode);
mode = new Mode(ModeEnum.PostgreSQL.name());
......
......@@ -584,7 +584,7 @@ public class MetaTable extends Table {
Value.STRING_IGNORECASE : Value.STRING;
name = nameType;
} else {
dataType = DataType.getTypeByName(nameType.substring(idx + 1)).type;
dataType = DataType.getTypeByName(nameType.substring(idx + 1), database.getMode()).type;
name = nameType.substring(0, idx);
}
cols[i] = new Column(name, dataType);
......
......@@ -26,6 +26,7 @@ import java.util.HashMap;
import java.util.UUID;
import org.h2.api.ErrorCode;
import org.h2.api.TimestampWithTimeZone;
import org.h2.engine.Mode;
import org.h2.engine.SessionInterface;
import org.h2.engine.SysProperties;
import org.h2.jdbc.JdbcArray;
......@@ -1192,13 +1193,17 @@ public class DataType {
* Get a data type object from a type name.
*
* @param s the type name
* @param mode database mode
* @return the data type object
*/
public static DataType getTypeByName(String s) {
DataType result = TYPES_BY_NAME.get(s);
public static DataType getTypeByName(String s, Mode mode) {
DataType result = mode.typeByNameMap.get(s);
if (result == null) {
result = TYPES_BY_NAME.get(s);
if (result == null && JdbcUtils.customDataTypesHandler != null) {
result = JdbcUtils.customDataTypesHandler.getDataTypeByName(s);
}
}
return result;
}
......
......@@ -10,6 +10,7 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.sql.Types;
import java.text.SimpleDateFormat;
import java.util.Arrays;
......@@ -41,6 +42,7 @@ public class TestCompatibilityOracle extends TestBase {
testToDate();
testForbidEmptyInClause();
testSpecialTypes();
testDate();
}
private void testNotNullSyntax() throws SQLException {
......@@ -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)
throws SQLException {
SimpleDateFormat iso8601 = new SimpleDateFormat(
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论