提交 2ff6f9b1 编写于 作者: S serge-rider

#238 Time and timestamp with time zone support (abstract + Oracle)


Former-commit-id: 62d1ae3d
上级 198f885c
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2018 Serge Rider (serge@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jkiss.dbeaver.ext.oracle.data;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.ext.oracle.model.OracleConstants;
import org.jkiss.dbeaver.model.data.DBDDataFormatter;
import org.jkiss.dbeaver.model.data.DBDDataFormatterProfile;
import org.jkiss.dbeaver.model.impl.jdbc.data.handlers.JDBCTemporalAccessorValueHandler;
import org.jkiss.dbeaver.model.struct.DBSTypedObject;
import java.sql.Types;
import java.time.format.DateTimeFormatter;
/**
* Object type support
*/
public class OracleTemporalAccessorValueHandler extends JDBCTemporalAccessorValueHandler {
private static final DateTimeFormatter DEFAULT_DATETIME_FORMAT = DateTimeFormatter.ofPattern("'TIMESTAMP '''yyyy-MM-dd HH:mm:ss.nnnnnn''");
private static final DateTimeFormatter DEFAULT_DATE_FORMAT = DateTimeFormatter.ofPattern("'DATE '''yyyy-MM-dd''");
private static final DateTimeFormatter DEFAULT_TIME_FORMAT = DateTimeFormatter.ofPattern("'TIME '''HH:mm:ss.SSS''");
public OracleTemporalAccessorValueHandler(DBDDataFormatterProfile formatterProfile)
{
super(formatterProfile);
}
@Nullable
@Override
public DateTimeFormatter getNativeValueFormat(DBSTypedObject type) {
switch (type.getTypeID()) {
case Types.TIMESTAMP:
return DEFAULT_DATETIME_FORMAT;
case Types.TIMESTAMP_WITH_TIMEZONE:
case OracleConstants.DATA_TYPE_TIMESTAMP_WITH_TIMEZONE:
case OracleConstants.DATA_TYPE_TIMESTAMP_WITH_LOCAL_TIMEZONE:
return DEFAULT_DATETIME_FORMAT;
case Types.TIME:
return DEFAULT_TIME_FORMAT;
case Types.TIME_WITH_TIMEZONE:
return DEFAULT_TIME_FORMAT;
case Types.DATE:
return DEFAULT_DATE_FORMAT;
}
return super.getNativeValueFormat(type);
}
@Override
protected String getFormatterId(DBSTypedObject column) {
switch (column.getTypeID()) {
case OracleConstants.DATA_TYPE_TIMESTAMP_WITH_TIMEZONE:
case OracleConstants.DATA_TYPE_TIMESTAMP_WITH_LOCAL_TIMEZONE:
return DBDDataFormatter.TYPE_NAME_TIMESTAMP;
default:
return super.getFormatterId(column);
}
}
@Override
protected boolean isZonedType(DBSTypedObject type) {
if (type.getTypeID() == OracleConstants.DATA_TYPE_TIMESTAMP_WITH_TIMEZONE) {
return true;
}
return super.isZonedType(type);
}
}
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
* Copyright (C) 2010-2018 Serge Rider (serge@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -45,6 +45,11 @@ public class OracleValueHandlerProvider implements DBDValueHandlerProvider {
return OracleBFILEValueHandler.INSTANCE;
} else if (typedObject.getTypeID() == java.sql.Types.STRUCT) {
return OracleObjectValueHandler.INSTANCE;
} else if (typedObject.getTypeID() == Types.TIME_WITH_TIMEZONE ||
typedObject.getTypeID() == Types.TIMESTAMP_WITH_TIMEZONE ||
typedObject.getTypeID() == OracleConstants.DATA_TYPE_TIMESTAMP_WITH_TIMEZONE)
{
return new OracleTemporalAccessorValueHandler(preferences.getDataFormatterProfile());
} else if (typeName.contains("TIMESTAMP") || typedObject.getDataKind() == DBPDataKind.DATETIME) {
return new OracleTimestampValueHandler(preferences.getDataFormatterProfile());
} else {
......
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
* Copyright (C) 2010-2018 Serge Rider (serge@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -79,8 +79,10 @@ public class DBConstants {
public static final String TYPE_NAME_JSON2 = TYPE_NAME_JSON.toLowerCase(Locale.ENGLISH);
public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";
public static final String DEFAULT_TIME_TZ_FORMAT = "HH:mm:ss Z";
public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
public static final String DEFAULT_TIMESTAMP_FORMAT = "yyyy-MM-dd HH:mm:ss.SSS";
public static final String DEFAULT_TIMESTAMP_TZ_FORMAT = "yyyy-MM-dd HH:mm:ss.SSS'Z'";
public static final String DEFAULT_ISO_TIMESTAMP_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
......
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2018 Serge Rider (serge@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jkiss.dbeaver.model.impl.data;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.data.DBDDataFormatter;
import org.jkiss.dbeaver.model.data.DBDDataFormatterProfile;
import org.jkiss.dbeaver.model.data.DBDDisplayFormat;
import org.jkiss.dbeaver.model.exec.DBCException;
import org.jkiss.dbeaver.model.exec.DBCSession;
import org.jkiss.dbeaver.model.impl.data.formatters.DefaultDataFormatter;
import org.jkiss.dbeaver.model.struct.DBSTypedObject;
import java.text.ParseException;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.time.temporal.TemporalAccessor;
import java.util.Date;
/**
* Date/time value handler
*/
public abstract class TemporalAccessorValueHandler extends BaseValueHandler {
protected static final Log log = Log.getLog(TemporalAccessorValueHandler.class);
private final DBDDataFormatterProfile formatterProfile;
protected DBDDataFormatter formatter;
public TemporalAccessorValueHandler(DBDDataFormatterProfile formatterProfile)
{
this.formatterProfile = formatterProfile;
}
@NotNull
@Override
public Class<Date> getValueObjectType(@NotNull DBSTypedObject attribute)
{
return Date.class;
}
@Override
public TemporalAccessor getValueFromObject(@NotNull DBCSession session, @NotNull DBSTypedObject type, Object object, boolean copy) throws DBCException
{
if (object == null) {
return null;
} else if (object instanceof TemporalAccessor) {
return (TemporalAccessor) object;
} else if (object instanceof String) {
String strValue = (String)object;
try {
return (TemporalAccessor) getFormatter(type).parseValue(strValue, isZonedType(type) ? ZonedDateTime.class : LocalDateTime.class);
} catch (ParseException e) {
// Try to parse with standard date/time formats
try {
return ZonedDateTime.parse((CharSequence) object);
} catch (Exception e1) {
log.debug("Can't parse string value [" + strValue + "] to date/time value", e);
return null;
}
}
} else {
throw new DBCException("Bad temporal accessor value: " + object);
}
}
@NotNull
@Override
public String getValueDisplayString(@NotNull DBSTypedObject column, Object value, @NotNull DBDDisplayFormat format) {
if (value == null) {
return super.getValueDisplayString(column, null, format);
}
try {
return getFormatter(column).formatValue(value);
} catch (Exception e) {
return String.valueOf(value);
}
}
@NotNull
protected DBDDataFormatter getFormatter(DBSTypedObject column)
{
if (formatter == null) {
try {
formatter = formatterProfile.createFormatter(getFormatterId(column), column);
} catch (Exception e) {
log.error("Can't create formatter for zoned datetime value handler", e); //$NON-NLS-1$
formatter = DefaultDataFormatter.INSTANCE;
}
}
return formatter;
}
protected abstract boolean isZonedType(DBSTypedObject type);
@NotNull
protected abstract String getFormatterId(DBSTypedObject column);
}
\ No newline at end of file
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
* Copyright (C) 2010-2018 Serge Rider (serge@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -24,6 +24,8 @@ import org.jkiss.utils.time.ExtendedDateFormat;
import java.text.DateFormat;
import java.text.FieldPosition;
import java.text.ParseException;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;
import java.util.Locale;
import java.util.Map;
......@@ -35,6 +37,7 @@ public class DateTimeDataFormatter implements DBDDataFormatter {
private DateFormat dateFormat;
private StringBuffer buffer;
private FieldPosition position;
private DateTimeFormatter dateTimeFormatter;
@Override
public void init(DBSTypedObject type, Locale locale, Map<Object, Object> properties)
......@@ -45,6 +48,7 @@ public class DateTimeDataFormatter implements DBDDataFormatter {
locale);
buffer = new StringBuffer();
position = new FieldPosition(0);
dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);
}
@Override
......@@ -56,6 +60,9 @@ public class DateTimeDataFormatter implements DBDDataFormatter {
@Override
public String formatValue(Object value)
{
if (value instanceof TemporalAccessor) {
return dateTimeFormatter.format((TemporalAccessor) value);
}
synchronized (dateFormat) {
buffer.setLength(0);
return value == null ? null : dateFormat.format(value, buffer, position).toString();
......@@ -65,6 +72,9 @@ public class DateTimeDataFormatter implements DBDDataFormatter {
@Override
public Object parseValue(String value, Class<?> typeHint) throws ParseException
{
if (typeHint != null && TemporalAccessor.class.isAssignableFrom(typeHint)) {
return dateTimeFormatter.parse(value);
}
return dateFormat.parse(value);
}
......
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2017 Serge Rider (serge@jkiss.org)
* Copyright (C) 2010-2018 Serge Rider (serge@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -44,9 +44,9 @@ import java.util.Date;
*/
public class JDBCDateTimeValueHandler extends DateTimeCustomValueHandler {
protected static final SimpleDateFormat DEFAULT_DATETIME_FORMAT = new SimpleDateFormat("''" + DBConstants.DEFAULT_TIMESTAMP_FORMAT + "''");
protected static final SimpleDateFormat DEFAULT_DATE_FORMAT = new SimpleDateFormat("''" + DBConstants.DEFAULT_DATE_FORMAT + "''");
protected static final SimpleDateFormat DEFAULT_TIME_FORMAT = new SimpleDateFormat("''" + DBConstants.DEFAULT_TIME_FORMAT + "''");
public static final SimpleDateFormat DEFAULT_DATETIME_FORMAT = new SimpleDateFormat("''" + DBConstants.DEFAULT_TIMESTAMP_FORMAT + "''");
public static final SimpleDateFormat DEFAULT_DATE_FORMAT = new SimpleDateFormat("''" + DBConstants.DEFAULT_DATE_FORMAT + "''");
public static final SimpleDateFormat DEFAULT_TIME_FORMAT = new SimpleDateFormat("''" + DBConstants.DEFAULT_TIME_FORMAT + "''");
public JDBCDateTimeValueHandler(DBDDataFormatterProfile formatterProfile)
{
......@@ -182,9 +182,13 @@ public class JDBCDateTimeValueHandler extends DateTimeCustomValueHandler {
protected String getFormatterId(DBSTypedObject column)
{
switch (column.getTypeID()) {
case Types.TIME: return DBDDataFormatter.TYPE_NAME_TIME;
case Types.DATE: return DBDDataFormatter.TYPE_NAME_DATE;
default: return DBDDataFormatter.TYPE_NAME_TIMESTAMP;
case Types.TIME:
case Types.TIME_WITH_TIMEZONE:
return DBDDataFormatter.TYPE_NAME_TIME;
case Types.DATE:
return DBDDataFormatter.TYPE_NAME_DATE;
default:
return DBDDataFormatter.TYPE_NAME_TIMESTAMP;
}
}
......
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2018 Serge Rider (serge@jkiss.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jkiss.dbeaver.model.impl.jdbc.data.handlers;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.model.DBConstants;
import org.jkiss.dbeaver.model.data.DBDDataFormatter;
import org.jkiss.dbeaver.model.data.DBDDataFormatterProfile;
import org.jkiss.dbeaver.model.data.DBDDisplayFormat;
import org.jkiss.dbeaver.model.exec.DBCException;
import org.jkiss.dbeaver.model.exec.DBCResultSet;
import org.jkiss.dbeaver.model.exec.DBCSession;
import org.jkiss.dbeaver.model.exec.DBCStatement;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCPreparedStatement;
import org.jkiss.dbeaver.model.exec.jdbc.JDBCResultSet;
import org.jkiss.dbeaver.model.impl.data.TemporalAccessorValueHandler;
import org.jkiss.dbeaver.model.messages.ModelMessages;
import org.jkiss.dbeaver.model.struct.DBSTypedObject;
import java.sql.SQLException;
import java.sql.Types;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;
/**
* JDBC zoned datetime value handler
*/
public class JDBCTemporalAccessorValueHandler extends TemporalAccessorValueHandler {
public static final DateTimeFormatter DEFAULT_DATE_FORMAT = DateTimeFormatter.ofPattern("''" + DBConstants.DEFAULT_DATE_FORMAT + "''");
public static final DateTimeFormatter DEFAULT_TIME_FORMAT = DateTimeFormatter.ofPattern("''" + DBConstants.DEFAULT_TIME_FORMAT + "''");
public static final DateTimeFormatter DEFAULT_TIME_TZ_FORMAT = DateTimeFormatter.ofPattern("''" + DBConstants.DEFAULT_TIME_TZ_FORMAT + "''");
public static final DateTimeFormatter DEFAULT_TIMESTAMP_FORMAT = DateTimeFormatter.ofPattern("''" + DBConstants.DEFAULT_TIMESTAMP_FORMAT + "''");
public static final DateTimeFormatter DEFAULT_TIMESTAMP_TZ_FORMAT = DateTimeFormatter.ofPattern("''" + DBConstants.DEFAULT_TIMESTAMP_TZ_FORMAT + "''");
public JDBCTemporalAccessorValueHandler(DBDDataFormatterProfile formatterProfile)
{
super(formatterProfile);
}
@Override
public Object fetchValueObject(@NotNull DBCSession session, @NotNull DBCResultSet resultSet, @NotNull DBSTypedObject type, int index) throws DBCException {
try {
if (resultSet instanceof JDBCResultSet) {
JDBCResultSet dbResults = (JDBCResultSet) resultSet;
if (isZonedType(type)) {
return dbResults.getObject(index + 1, ZonedDateTime.class);
} else {
return dbResults.getObject(index + 1, LocalDateTime.class);
}
} else {
return resultSet.getAttributeValue(index);
}
}
catch (SQLException e) {
throw new DBCException(e, session.getDataSource());
}
}
@Override
public void bindValueObject(@NotNull DBCSession session, @NotNull DBCStatement statement, @NotNull DBSTypedObject type, int index, @Nullable Object value) throws DBCException {
try {
JDBCPreparedStatement dbStat = (JDBCPreparedStatement)statement;
// JDBC uses 1-based indexes
if (value == null) {
dbStat.setNull(index + 1, type.getTypeID());
} else if (value instanceof TemporalAccessor) {
dbStat.setObject(index + 1, value);
}
}
catch (SQLException e) {
throw new DBCException(ModelMessages.model_jdbc_exception_could_not_bind_statement_parameter, e);
}
}
@NotNull
@Override
public String getValueDisplayString(@NotNull DBSTypedObject column, Object value, @NotNull DBDDisplayFormat format)
{
if (value instanceof TemporalAccessor && format == DBDDisplayFormat.NATIVE) {
DateTimeFormatter nativeFormat = getNativeValueFormat(column);
if (nativeFormat != null) {
try {
return nativeFormat.format((TemporalAccessor) value);
} catch (Exception e) {
log.error("Error formatting date", e);
}
}
}
return super.getValueDisplayString(column, value, format);
}
@Nullable
protected DateTimeFormatter getNativeValueFormat(DBSTypedObject type) {
switch (type.getTypeID()) {
case Types.TIMESTAMP:
return DEFAULT_TIMESTAMP_FORMAT;
case Types.TIMESTAMP_WITH_TIMEZONE:
return DEFAULT_TIMESTAMP_TZ_FORMAT;
case Types.TIME:
return DEFAULT_TIME_FORMAT;
case Types.TIME_WITH_TIMEZONE:
return DEFAULT_TIME_TZ_FORMAT;
case Types.DATE:
return DEFAULT_DATE_FORMAT;
}
return null;
}
@NotNull
protected String getFormatterId(DBSTypedObject column)
{
switch (column.getTypeID()) {
case Types.TIME:
case Types.TIME_WITH_TIMEZONE:
return DBDDataFormatter.TYPE_NAME_TIME;
case Types.DATE:
return DBDDataFormatter.TYPE_NAME_DATE;
default:
return DBDDataFormatter.TYPE_NAME_TIMESTAMP;
}
}
@Override
protected boolean isZonedType(DBSTypedObject type) {
switch (type.getTypeID()) {
case Types.TIME_WITH_TIMEZONE:
case Types.TIMESTAMP_WITH_TIMEZONE:
return true;
default:
return false;
}
}
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册