提交 547dfcbd authored 作者: thomasmueller's avatar thomasmueller

Make the JDBC client independent of the database engine

上级 aec8b449
...@@ -15,8 +15,8 @@ import org.h2.bnf.RuleElement; ...@@ -15,8 +15,8 @@ import org.h2.bnf.RuleElement;
import org.h2.bnf.RuleHead; import org.h2.bnf.RuleHead;
import org.h2.bnf.RuleList; import org.h2.bnf.RuleList;
import org.h2.bnf.Sentence; import org.h2.bnf.Sentence;
import org.h2.command.Parser;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.util.ParserUtil;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
/** /**
...@@ -154,7 +154,7 @@ public class DbContextRule implements Rule { ...@@ -154,7 +154,7 @@ public class DbContextRule implements Rule {
break; break;
} }
String alias = up.substring(0, i); String alias = up.substring(0, i);
if (Parser.isKeyword(alias, true)) { if (ParserUtil.isKeyword(alias, true)) {
break; break;
} }
s = s.substring(alias.length()); s = s.substring(alias.length());
...@@ -301,7 +301,7 @@ public class DbContextRule implements Rule { ...@@ -301,7 +301,7 @@ public class DbContextRule implements Rule {
return s; return s;
} }
String alias = up.substring(0, i); String alias = up.substring(0, i);
if ("SET".equals(alias) || Parser.isKeyword(alias, true)) { if ("SET".equals(alias) || ParserUtil.isKeyword(alias, true)) {
return s; return s;
} }
if (newAlias) { if (newAlias) {
......
...@@ -148,6 +148,7 @@ import org.h2.table.TableFilter.TableFilterVisitor; ...@@ -148,6 +148,7 @@ import org.h2.table.TableFilter.TableFilterVisitor;
import org.h2.table.TableView; import org.h2.table.TableView;
import org.h2.util.MathUtils; import org.h2.util.MathUtils;
import org.h2.util.New; import org.h2.util.New;
import org.h2.util.ParserUtil;
import org.h2.util.StatementBuilder; import org.h2.util.StatementBuilder;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
import org.h2.value.CompareMode; import org.h2.value.CompareMode;
...@@ -186,15 +187,18 @@ public class Parser { ...@@ -186,15 +187,18 @@ public class Parser {
CHAR_DOLLAR_QUOTED_STRING = 9; CHAR_DOLLAR_QUOTED_STRING = 9;
// this are token types // this are token types
private static final int KEYWORD = 1, IDENTIFIER = 2, PARAMETER = 3, private static final int KEYWORD = ParserUtil.KEYWORD;
END = 4, VALUE = 5; private static final int IDENTIFIER = ParserUtil.IDENTIFIER;
private static final int EQUAL = 6, BIGGER_EQUAL = 7, BIGGER = 8; private static final int NULL = ParserUtil.NULL;
private static final int SMALLER = 9, SMALLER_EQUAL = 10, NOT_EQUAL = 11, private static final int TRUE = ParserUtil.TRUE;
AT = 12; private static final int FALSE = ParserUtil.FALSE;
private static final int MINUS = 13, PLUS = 14, STRING_CONCAT = 15; private static final int ROWNUM = ParserUtil.ROWNUM;
private static final int OPEN = 16, CLOSE = 17, NULL = 18, TRUE = 19, private static final int PARAMETER = 10, END = 11, VALUE = 12;
FALSE = 20; private static final int EQUAL = 13, BIGGER_EQUAL = 14, BIGGER = 15;
private static final int ROWNUM = 24; private static final int SMALLER = 16, SMALLER_EQUAL = 17, NOT_EQUAL = 18;
private static final int AT = 19;
private static final int MINUS = 20, PLUS = 21, STRING_CONCAT = 22;
private static final int OPEN = 23, CLOSE = 24;
private static final int SPATIAL_INTERSECTS = 25; private static final int SPATIAL_INTERSECTS = 25;
private static final Comparator<TableFilter> TABLE_FILTER_COMPARATOR = private static final Comparator<TableFilter> TABLE_FILTER_COMPARATOR =
...@@ -4170,140 +4174,11 @@ public class Parser { ...@@ -4170,140 +4174,11 @@ public class Parser {
// if not yet converted to uppercase, do it now // if not yet converted to uppercase, do it now
s = StringUtils.toUpperEnglish(s); s = StringUtils.toUpperEnglish(s);
} }
return isKeyword(s, false); return ParserUtil.isKeyword(s, false);
}
/**
* Checks if this string is a SQL keyword.
*
* @param s the token to check
* @param supportOffsetFetch if OFFSET and FETCH are keywords
* @return true if it is a keyword
*/
public static boolean isKeyword(String s, boolean supportOffsetFetch) {
if (s == null || s.length() == 0) {
return false;
}
return getSaveTokenType(s, supportOffsetFetch, false) != IDENTIFIER;
} }
private static int getSaveTokenType(String s, boolean supportOffsetFetch, boolean functionsAsKeywords) { private static int getSaveTokenType(String s, boolean supportOffsetFetch, boolean functionsAsKeywords) {
switch (s.charAt(0)) { return ParserUtil.getSaveTokenType(s, supportOffsetFetch, functionsAsKeywords);
case 'A':
return getKeywordOrIdentifier(s, "ALL", KEYWORD);
case 'C':
if ("CHECK".equals(s)) {
return KEYWORD;
} else if ("CONSTRAINT".equals(s)) {
return KEYWORD;
} else if ("CROSS".equals(s)) {
return KEYWORD;
}
if (functionsAsKeywords) {
if ("CURRENT_DATE".equals(s) || "CURRENT_TIME".equals(s) || "CURRENT_TIMESTAMP".equals(s)) {
return KEYWORD;
}
}
return IDENTIFIER;
case 'D':
return getKeywordOrIdentifier(s, "DISTINCT", KEYWORD);
case 'E':
if ("EXCEPT".equals(s)) {
return KEYWORD;
}
return getKeywordOrIdentifier(s, "EXISTS", KEYWORD);
case 'F':
if ("FROM".equals(s)) {
return KEYWORD;
} else if ("FOR".equals(s)) {
return KEYWORD;
} else if ("FOREIGN".equals(s)) {
return KEYWORD;
} else if ("FULL".equals(s)) {
return KEYWORD;
} else if (supportOffsetFetch && "FETCH".equals(s)) {
return KEYWORD;
}
return getKeywordOrIdentifier(s, "FALSE", FALSE);
case 'G':
return getKeywordOrIdentifier(s, "GROUP", KEYWORD);
case 'H':
return getKeywordOrIdentifier(s, "HAVING", KEYWORD);
case 'I':
if ("INNER".equals(s)) {
return KEYWORD;
} else if ("INTERSECT".equals(s)) {
return KEYWORD;
}
return getKeywordOrIdentifier(s, "IS", KEYWORD);
case 'J':
return getKeywordOrIdentifier(s, "JOIN", KEYWORD);
case 'L':
if ("LIMIT".equals(s)) {
return KEYWORD;
}
return getKeywordOrIdentifier(s, "LIKE", KEYWORD);
case 'M':
return getKeywordOrIdentifier(s, "MINUS", KEYWORD);
case 'N':
if ("NOT".equals(s)) {
return KEYWORD;
} else if ("NATURAL".equals(s)) {
return KEYWORD;
}
return getKeywordOrIdentifier(s, "NULL", NULL);
case 'O':
if ("ON".equals(s)) {
return KEYWORD;
} else if (supportOffsetFetch && "OFFSET".equals(s)) {
return KEYWORD;
}
return getKeywordOrIdentifier(s, "ORDER", KEYWORD);
case 'P':
return getKeywordOrIdentifier(s, "PRIMARY", KEYWORD);
case 'R':
return getKeywordOrIdentifier(s, "ROWNUM", ROWNUM);
case 'S':
if ("SELECT".equals(s)) {
return KEYWORD;
}
if (functionsAsKeywords) {
if ("SYSDATE".equals(s) || "SYSTIME".equals(s) || "SYSTIMESTAMP".equals(s)) {
return KEYWORD;
}
}
return IDENTIFIER;
case 'T':
if ("TRUE".equals(s)) {
return TRUE;
}
if (functionsAsKeywords) {
if ("TODAY".equals(s)) {
return KEYWORD;
}
}
return IDENTIFIER;
case 'U':
if ("UNIQUE".equals(s)) {
return KEYWORD;
}
return getKeywordOrIdentifier(s, "UNION", KEYWORD);
case 'W':
if ("WITH".equals(s)) {
return KEYWORD;
}
return getKeywordOrIdentifier(s, "WHERE", KEYWORD);
default:
return IDENTIFIER;
}
}
private static int getKeywordOrIdentifier(String s1, String s2,
int keywordType) {
if (s1.equals(s2)) {
return keywordType;
}
return IDENTIFIER;
} }
private Column parseColumnForTable(String columnName, private Column parseColumnForTable(String columnName,
...@@ -6890,8 +6765,9 @@ public class Parser { ...@@ -6890,8 +6765,9 @@ public class Parser {
if (s == null) { if (s == null) {
return "\"\""; return "\"\"";
} }
if (isSimpleIdentifier(s, false)) if (isSimpleIdentifier(s, false)) {
return s; return s;
}
return StringUtils.quoteIdentifier(s); return StringUtils.quoteIdentifier(s);
} }
...@@ -6904,22 +6780,7 @@ public class Parser { ...@@ -6904,22 +6780,7 @@ public class Parser {
* @throws NullPointerException if s is {@code null} * @throws NullPointerException if s is {@code null}
*/ */
public static boolean isSimpleIdentifier(String s, boolean functionsAsKeywords) { public static boolean isSimpleIdentifier(String s, boolean functionsAsKeywords) {
if (s.length() == 0) { return ParserUtil.isSimpleIdentifier(s, functionsAsKeywords);
return false;
}
char c = s.charAt(0);
// lowercase a-z is quoted as well
if ((!Character.isLetter(c) && c != '_') || Character.isLowerCase(c)) {
return false;
}
for (int i = 1, length = s.length(); i < length; i++) {
c = s.charAt(i);
if ((!Character.isLetterOrDigit(c) && c != '_') ||
Character.isLowerCase(c)) {
return false;
}
}
return getSaveTokenType(s, true, functionsAsKeywords) == IDENTIFIER;
} }
public void setLiteralsChecked(boolean literalsChecked) { public void setLiteralsChecked(boolean literalsChecked) {
......
...@@ -12,6 +12,7 @@ import org.h2.engine.Session; ...@@ -12,6 +12,7 @@ import org.h2.engine.Session;
import org.h2.engine.SysProperties; import org.h2.engine.SysProperties;
import org.h2.index.IndexCondition; import org.h2.index.IndexCondition;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.table.Column;
import org.h2.table.ColumnResolver; import org.h2.table.ColumnResolver;
import org.h2.table.TableFilter; import org.h2.table.TableFilter;
import org.h2.util.MathUtils; import org.h2.util.MathUtils;
...@@ -202,9 +203,10 @@ public class Comparison extends Condition { ...@@ -202,9 +203,10 @@ public class Comparison extends Condition {
// to constant type, but vise versa, then let's do this here // to constant type, but vise versa, then let's do this here
// once. // once.
if (constType != resType) { if (constType != resType) {
Column column = ((ExpressionColumn) left).getColumn();
right = ValueExpression.get(r.convertTo(resType, right = ValueExpression.get(r.convertTo(resType,
MathUtils.convertLongToInt(left.getPrecision()), MathUtils.convertLongToInt(left.getPrecision()),
session.getDatabase().getMode(), ((ExpressionColumn) left).getColumn())); session.getDatabase().getMode(), column, column.getEnumerators()));
} }
} else if (right instanceof Parameter) { } else if (right instanceof Parameter) {
((Parameter) right).setColumn( ((Parameter) right).setColumn(
......
...@@ -18,6 +18,7 @@ import java.sql.Timestamp; ...@@ -18,6 +18,7 @@ import java.sql.Timestamp;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashMap; import java.util.HashMap;
import java.util.Locale; import java.util.Locale;
import java.util.regex.Pattern; import java.util.regex.Pattern;
...@@ -854,7 +855,7 @@ public class Function extends Expression implements FunctionCall { ...@@ -854,7 +855,7 @@ public class Function extends Expression implements FunctionCall {
case SECOND: case SECOND:
case WEEK: case WEEK:
case YEAR: case YEAR:
result = ValueInt.get(DateTimeUtils.getDatePart(v0, info.type)); result = ValueInt.get(getDatePart(v0, info.type));
break; break;
case MONTH_NAME: { case MONTH_NAME: {
SimpleDateFormat monthName = new SimpleDateFormat("MMMM", SimpleDateFormat monthName = new SimpleDateFormat("MMMM",
...@@ -1493,7 +1494,7 @@ public class Function extends Expression implements FunctionCall { ...@@ -1493,7 +1494,7 @@ public class Function extends Expression implements FunctionCall {
break; break;
case EXTRACT: { case EXTRACT: {
int field = getDatePart(v0.getString()); int field = getDatePart(v0.getString());
result = ValueInt.get(DateTimeUtils.getDatePart(v1, field)); result = ValueInt.get(getDatePart(v1, field));
break; break;
} }
case FORMATDATETIME: { case FORMATDATETIME: {
...@@ -2763,6 +2764,52 @@ public class Function extends Expression implements FunctionCall { ...@@ -2763,6 +2764,52 @@ public class Function extends Expression implements FunctionCall {
} }
} }
/**
* Get the specified field of a date, however with years normalized to
* positive or negative, and month starting with 1.
*
* @param date the date value
* @param field the field type, see {@link Function} for constants
* @return the value
*/
public static int getDatePart(Value date, int field) {
long[] a = DateTimeUtils.dateAndTimeFromValue(date);
long dateValue = a[0];
long timeNanos = a[1];
switch (field) {
case Function.YEAR:
return DateTimeUtils.yearFromDateValue(dateValue);
case Function.MONTH:
return DateTimeUtils.monthFromDateValue(dateValue);
case Function.DAY_OF_MONTH:
return DateTimeUtils.dayFromDateValue(dateValue);
case Function.HOUR:
return (int) (timeNanos / 3_600_000_000_000L % 24);
case Function.MINUTE:
return (int) (timeNanos / 60_000_000_000L % 60);
case Function.SECOND:
return (int) (timeNanos / 1_000_000_000 % 60);
case Function.MILLISECOND:
return (int) (timeNanos / 1_000_000 % 1_000);
case Function.DAY_OF_YEAR:
return DateTimeUtils.getDayOfYear(dateValue);
case Function.DAY_OF_WEEK:
return DateTimeUtils.getSundayDayOfWeek(dateValue);
case Function.WEEK:
GregorianCalendar gc = DateTimeUtils.getCalendar();
return DateTimeUtils.getWeekOfYear(dateValue, gc.getFirstDayOfWeek() - 1, gc.getMinimalDaysInFirstWeek());
case Function.QUARTER:
return (DateTimeUtils.monthFromDateValue(dateValue) - 1) / 3 + 1;
case Function.ISO_YEAR:
return DateTimeUtils.getIsoWeekYear(dateValue);
case Function.ISO_WEEK:
return DateTimeUtils.getIsoWeekOfYear(dateValue);
case Function.ISO_DAY_OF_WEEK:
return DateTimeUtils.getIsoDayOfWeek(dateValue);
}
throw DbException.getUnsupportedException("getDatePart(" + date + ", " + field + ')');
}
@Override @Override
public Expression[] getArgs() { public Expression[] getArgs() {
return args; return args;
......
...@@ -13,13 +13,13 @@ import java.sql.Statement; ...@@ -13,13 +13,13 @@ import java.sql.Statement;
import java.util.ArrayList; import java.util.ArrayList;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.command.CommandInterface; import org.h2.command.CommandInterface;
import org.h2.command.Parser;
import org.h2.engine.SessionInterface; import org.h2.engine.SessionInterface;
import org.h2.engine.SysProperties; import org.h2.engine.SysProperties;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.message.TraceObject; import org.h2.message.TraceObject;
import org.h2.result.ResultInterface; import org.h2.result.ResultInterface;
import org.h2.util.New; import org.h2.util.New;
import org.h2.util.ParserUtil;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
/** /**
...@@ -1333,7 +1333,7 @@ public class JdbcStatement extends TraceObject implements Statement, JdbcStateme ...@@ -1333,7 +1333,7 @@ public class JdbcStatement extends TraceObject implements Statement, JdbcStateme
*/ */
@Override @Override
public boolean isSimpleIdentifier(String identifier) throws SQLException { public boolean isSimpleIdentifier(String identifier) throws SQLException {
return Parser.isSimpleIdentifier(identifier, true); return ParserUtil.isSimpleIdentifier(identifier, true);
} }
/** /**
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
*/ */
package org.h2.result; package org.h2.result;
import org.h2.engine.Session; import org.h2.engine.SessionInterface;
import org.h2.expression.Expression; import org.h2.expression.Expression;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.value.Value; import org.h2.value.Value;
...@@ -180,7 +180,7 @@ public abstract class LazyResult implements ResultInterface { ...@@ -180,7 +180,7 @@ public abstract class LazyResult implements ResultInterface {
} }
@Override @Override
public ResultInterface createShallowCopy(Session targetSession) { public ResultInterface createShallowCopy(SessionInterface targetSession) {
// Copying is impossible with lazy result. // Copying is impossible with lazy result.
return null; return null;
} }
......
...@@ -12,6 +12,7 @@ import java.util.Arrays; ...@@ -12,6 +12,7 @@ import java.util.Arrays;
import org.h2.engine.Database; import org.h2.engine.Database;
import org.h2.engine.Session; import org.h2.engine.Session;
import org.h2.engine.SessionInterface;
import org.h2.expression.Expression; import org.h2.expression.Expression;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.util.New; import org.h2.util.New;
...@@ -125,7 +126,7 @@ public class LocalResult implements ResultInterface, ResultTarget { ...@@ -125,7 +126,7 @@ public class LocalResult implements ResultInterface, ResultTarget {
* @return the copy if possible, or null if copying is not possible * @return the copy if possible, or null if copying is not possible
*/ */
@Override @Override
public LocalResult createShallowCopy(Session targetSession) { public LocalResult createShallowCopy(SessionInterface targetSession) {
if (external == null && (rows == null || rows.size() < rowCount)) { if (external == null && (rows == null || rows.size() < rowCount)) {
return null; return null;
} }
...@@ -141,7 +142,7 @@ public class LocalResult implements ResultInterface, ResultTarget { ...@@ -141,7 +142,7 @@ public class LocalResult implements ResultInterface, ResultTarget {
} }
LocalResult copy = new LocalResult(); LocalResult copy = new LocalResult();
copy.maxMemoryRows = this.maxMemoryRows; copy.maxMemoryRows = this.maxMemoryRows;
copy.session = targetSession; copy.session = (Session) targetSession;
copy.visibleColumnCount = this.visibleColumnCount; copy.visibleColumnCount = this.visibleColumnCount;
copy.expressions = this.expressions; copy.expressions = this.expressions;
copy.rowId = -1; copy.rowId = -1;
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
*/ */
package org.h2.result; package org.h2.result;
import org.h2.engine.Session; import org.h2.engine.SessionInterface;
import org.h2.value.Value; import org.h2.value.Value;
/** /**
...@@ -200,7 +200,7 @@ public interface ResultInterface extends AutoCloseable { ...@@ -200,7 +200,7 @@ public interface ResultInterface extends AutoCloseable {
* @param targetSession the session of the copy * @param targetSession the session of the copy
* @return the copy if possible, or null if copying is not possible * @return the copy if possible, or null if copying is not possible
*/ */
ResultInterface createShallowCopy(Session targetSession); ResultInterface createShallowCopy(SessionInterface targetSession);
/** /**
* Check if this result set contains the given row. * Check if this result set contains the given row.
......
...@@ -7,7 +7,7 @@ package org.h2.result; ...@@ -7,7 +7,7 @@ package org.h2.result;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import org.h2.engine.Session; import org.h2.engine.SessionInterface;
import org.h2.engine.SessionRemote; import org.h2.engine.SessionRemote;
import org.h2.engine.SysProperties; import org.h2.engine.SysProperties;
import org.h2.message.DbException; import org.h2.message.DbException;
...@@ -271,7 +271,7 @@ public class ResultRemote implements ResultInterface { ...@@ -271,7 +271,7 @@ public class ResultRemote implements ResultInterface {
} }
@Override @Override
public ResultInterface createShallowCopy(Session targetSession) { public ResultInterface createShallowCopy(SessionInterface targetSession) {
// The operation is not supported on remote result. // The operation is not supported on remote result.
return null; return null;
} }
......
...@@ -173,7 +173,7 @@ public class Column { ...@@ -173,7 +173,7 @@ public class Column {
*/ */
public Value convert(Value v, Mode mode) { public Value convert(Value v, Mode mode) {
try { try {
return v.convertTo(type, MathUtils.convertLongToInt(precision), mode, this); return v.convertTo(type, MathUtils.convertLongToInt(precision), mode, this, getEnumerators());
} catch (DbException e) { } catch (DbException e) {
if (e.getErrorCode() == ErrorCode.DATA_CONVERSION_ERROR_1) { if (e.getErrorCode() == ErrorCode.DATA_CONVERSION_ERROR_1) {
String target = (table == null ? "" : table.getName() + ": ") + String target = (table == null ? "" : table.getName() + ": ") +
......
...@@ -16,7 +16,6 @@ import java.util.Locale; ...@@ -16,7 +16,6 @@ import java.util.Locale;
import java.util.TimeZone; import java.util.TimeZone;
import org.h2.api.ErrorCode; import org.h2.api.ErrorCode;
import org.h2.engine.Mode; import org.h2.engine.Mode;
import org.h2.expression.Function;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.value.Value; import org.h2.value.Value;
import org.h2.value.ValueDate; import org.h2.value.ValueDate;
...@@ -111,7 +110,7 @@ public class DateTimeUtils { ...@@ -111,7 +110,7 @@ public class DateTimeUtils {
* *
* @return a calendar instance. A cached instance is returned where possible * @return a calendar instance. A cached instance is returned where possible
*/ */
private static GregorianCalendar getCalendar() { public static GregorianCalendar getCalendar() {
GregorianCalendar c = CACHED_CALENDAR.get(); GregorianCalendar c = CACHED_CALENDAR.get();
if (c == null) { if (c == null) {
c = DateTimeUtils.createGregorianCalendar(); c = DateTimeUtils.createGregorianCalendar();
...@@ -591,52 +590,6 @@ public class DateTimeUtils { ...@@ -591,52 +590,6 @@ public class DateTimeUtils {
return new long[] {dateValue, timeNanos}; return new long[] {dateValue, timeNanos};
} }
/**
* Get the specified field of a date, however with years normalized to
* positive or negative, and month starting with 1.
*
* @param date the date value
* @param field the field type, see {@link Function} for constants
* @return the value
*/
public static int getDatePart(Value date, int field) {
long[] a = dateAndTimeFromValue(date);
long dateValue = a[0];
long timeNanos = a[1];
switch (field) {
case Function.YEAR:
return yearFromDateValue(dateValue);
case Function.MONTH:
return monthFromDateValue(dateValue);
case Function.DAY_OF_MONTH:
return dayFromDateValue(dateValue);
case Function.HOUR:
return (int) (timeNanos / 3_600_000_000_000L % 24);
case Function.MINUTE:
return (int) (timeNanos / 60_000_000_000L % 60);
case Function.SECOND:
return (int) (timeNanos / 1_000_000_000 % 60);
case Function.MILLISECOND:
return (int) (timeNanos / 1_000_000 % 1_000);
case Function.DAY_OF_YEAR:
return getDayOfYear(dateValue);
case Function.DAY_OF_WEEK:
return getSundayDayOfWeek(dateValue);
case Function.WEEK:
GregorianCalendar gc = getCalendar();
return getWeekOfYear(dateValue, gc.getFirstDayOfWeek() - 1, gc.getMinimalDaysInFirstWeek());
case Function.QUARTER:
return (monthFromDateValue(dateValue) - 1) / 3 + 1;
case Function.ISO_YEAR:
return getIsoWeekYear(dateValue);
case Function.ISO_WEEK:
return getIsoWeekOfYear(dateValue);
case Function.ISO_DAY_OF_WEEK:
return getIsoDayOfWeek(dateValue);
}
throw DbException.getUnsupportedException("getDatePart(" + date + ", " + field + ')');
}
/** /**
* Get the year (positive or negative) from a calendar. * Get the year (positive or negative) from a calendar.
* *
......
...@@ -24,7 +24,6 @@ import org.h2.engine.Mode; ...@@ -24,7 +24,6 @@ import org.h2.engine.Mode;
import org.h2.engine.SysProperties; import org.h2.engine.SysProperties;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.store.DataHandler; import org.h2.store.DataHandler;
import org.h2.table.Column;
import org.h2.tools.SimpleResultSet; import org.h2.tools.SimpleResultSet;
import org.h2.util.Bits; import org.h2.util.Bits;
import org.h2.util.DateTimeUtils; import org.h2.util.DateTimeUtils;
...@@ -604,7 +603,7 @@ public abstract class Value { ...@@ -604,7 +603,7 @@ public abstract class Value {
* @return the converted value * @return the converted value
*/ */
public final Value convertTo(int targetType, int precision, Mode mode) { public final Value convertTo(int targetType, int precision, Mode mode) {
return convertTo(targetType, precision, mode, null); return convertTo(targetType, precision, mode, null, null);
} }
/** /**
...@@ -615,11 +614,12 @@ public abstract class Value { ...@@ -615,11 +614,12 @@ public abstract class Value {
* The special constant <code>-1</code> is used to indicate that * The special constant <code>-1</code> is used to indicate that
* the precision plays no role when converting the value * the precision plays no role when converting the value
* @param mode the conversion mode * @param mode the conversion mode
* @param column the column that contains the ENUM datatype enumerators, * @param column the column (if any), used for to improve the error message if conversion fails
* @param enumerators the ENUM datatype enumerators (if any),
* for dealing with ENUM conversions * for dealing with ENUM conversions
* @return the converted value * @return the converted value
*/ */
public Value convertTo(int targetType, int precision, Mode mode, Column column) { public Value convertTo(int targetType, int precision, Mode mode, Object column, String[] enumerators) {
// converting NULL is done in ValueNull // converting NULL is done in ValueNull
// converting BLOB to CLOB and vice versa is done in ValueLob // converting BLOB to CLOB and vice versa is done in ValueLob
if (getType() == targetType) { if (getType() == targetType) {
...@@ -938,11 +938,11 @@ public abstract class Value { ...@@ -938,11 +938,11 @@ public abstract class Value {
case INT: case INT:
case LONG: case LONG:
case DECIMAL: case DECIMAL:
return ValueEnum.get(column.getEnumerators(), getInt()); return ValueEnum.get(enumerators, getInt());
case STRING: case STRING:
case STRING_IGNORECASE: case STRING_IGNORECASE:
case STRING_FIXED: case STRING_FIXED:
return ValueEnum.get(column.getEnumerators(), getString()); return ValueEnum.get(enumerators, getString());
default: default:
throw DbException.get( throw DbException.get(
ErrorCode.DATA_CONVERSION_ERROR_1, getString()); ErrorCode.DATA_CONVERSION_ERROR_1, getString());
...@@ -1154,51 +1154,51 @@ public abstract class Value { ...@@ -1154,51 +1154,51 @@ public abstract class Value {
return this; return this;
} }
private static byte convertToByte(long x, Column col) { private static byte convertToByte(long x, Object column) {
if (x > Byte.MAX_VALUE || x < Byte.MIN_VALUE) { if (x > Byte.MAX_VALUE || x < Byte.MIN_VALUE) {
throw DbException.get( throw DbException.get(
ErrorCode.NUMERIC_VALUE_OUT_OF_RANGE_2, Long.toString(x), getColumnName(col)); ErrorCode.NUMERIC_VALUE_OUT_OF_RANGE_2, Long.toString(x), getColumnName(column));
} }
return (byte) x; return (byte) x;
} }
private static short convertToShort(long x, Column col) { private static short convertToShort(long x, Object column) {
if (x > Short.MAX_VALUE || x < Short.MIN_VALUE) { if (x > Short.MAX_VALUE || x < Short.MIN_VALUE) {
throw DbException.get( throw DbException.get(
ErrorCode.NUMERIC_VALUE_OUT_OF_RANGE_2, Long.toString(x), getColumnName(col)); ErrorCode.NUMERIC_VALUE_OUT_OF_RANGE_2, Long.toString(x), getColumnName(column));
} }
return (short) x; return (short) x;
} }
private static int convertToInt(long x, Column col) { private static int convertToInt(long x, Object column) {
if (x > Integer.MAX_VALUE || x < Integer.MIN_VALUE) { if (x > Integer.MAX_VALUE || x < Integer.MIN_VALUE) {
throw DbException.get( throw DbException.get(
ErrorCode.NUMERIC_VALUE_OUT_OF_RANGE_2, Long.toString(x), getColumnName(col)); ErrorCode.NUMERIC_VALUE_OUT_OF_RANGE_2, Long.toString(x), getColumnName(column));
} }
return (int) x; return (int) x;
} }
private static long convertToLong(double x, Column col) { private static long convertToLong(double x, Object column) {
if (x > Long.MAX_VALUE || x < Long.MIN_VALUE) { if (x > Long.MAX_VALUE || x < Long.MIN_VALUE) {
// TODO document that +Infinity, -Infinity throw an exception and // TODO document that +Infinity, -Infinity throw an exception and
// NaN returns 0 // NaN returns 0
throw DbException.get( throw DbException.get(
ErrorCode.NUMERIC_VALUE_OUT_OF_RANGE_2, Double.toString(x), getColumnName(col)); ErrorCode.NUMERIC_VALUE_OUT_OF_RANGE_2, Double.toString(x), getColumnName(column));
} }
return Math.round(x); return Math.round(x);
} }
private static long convertToLong(BigDecimal x, Column col) { private static long convertToLong(BigDecimal x, Object column) {
if (x.compareTo(MAX_LONG_DECIMAL) > 0 || if (x.compareTo(MAX_LONG_DECIMAL) > 0 ||
x.compareTo(Value.MIN_LONG_DECIMAL) < 0) { x.compareTo(Value.MIN_LONG_DECIMAL) < 0) {
throw DbException.get( throw DbException.get(
ErrorCode.NUMERIC_VALUE_OUT_OF_RANGE_2, x.toString(), getColumnName(col)); ErrorCode.NUMERIC_VALUE_OUT_OF_RANGE_2, x.toString(), getColumnName(column));
} }
return x.setScale(0, BigDecimal.ROUND_HALF_UP).longValue(); return x.setScale(0, BigDecimal.ROUND_HALF_UP).longValue();
} }
private static String getColumnName(Column col) { private static String getColumnName(Object column) {
return col == null ? "" : col.getName(); return column == null ? "" : column.toString();
} }
/** /**
......
...@@ -10,7 +10,6 @@ import java.sql.SQLException; ...@@ -10,7 +10,6 @@ import java.sql.SQLException;
import java.util.Arrays; import java.util.Arrays;
import org.h2.engine.Mode; import org.h2.engine.Mode;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.table.Column;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
import com.vividsolutions.jts.geom.CoordinateSequence; import com.vividsolutions.jts.geom.CoordinateSequence;
import com.vividsolutions.jts.geom.CoordinateSequenceFilter; import com.vividsolutions.jts.geom.CoordinateSequenceFilter;
...@@ -273,11 +272,11 @@ public class ValueGeometry extends Value { ...@@ -273,11 +272,11 @@ public class ValueGeometry extends Value {
} }
@Override @Override
public Value convertTo(int targetType, int precision, Mode mode, Column column) { public Value convertTo(int targetType, int precision, Mode mode, Object column, String[] enumerators) {
if (targetType == Value.JAVA_OBJECT) { if (targetType == Value.JAVA_OBJECT) {
return this; return this;
} }
return super.convertTo(targetType, precision, mode, column); return super.convertTo(targetType, precision, mode, column, null);
} }
/** /**
......
...@@ -14,6 +14,7 @@ import java.io.Reader; ...@@ -14,6 +14,7 @@ import java.io.Reader;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.SQLException; import java.sql.SQLException;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.engine.Mode; import org.h2.engine.Mode;
import org.h2.engine.SysProperties; import org.h2.engine.SysProperties;
...@@ -26,7 +27,6 @@ import org.h2.store.FileStoreOutputStream; ...@@ -26,7 +27,6 @@ import org.h2.store.FileStoreOutputStream;
import org.h2.store.RangeInputStream; import org.h2.store.RangeInputStream;
import org.h2.store.RangeReader; import org.h2.store.RangeReader;
import org.h2.store.fs.FileUtils; import org.h2.store.fs.FileUtils;
import org.h2.table.Column;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
import org.h2.util.MathUtils; import org.h2.util.MathUtils;
import org.h2.util.SmallLRUCache; import org.h2.util.SmallLRUCache;
...@@ -499,12 +499,13 @@ public class ValueLob extends Value { ...@@ -499,12 +499,13 @@ public class ValueLob extends Value {
* The special constant <code>-1</code> is used to indicate that * The special constant <code>-1</code> is used to indicate that
* the precision plays no role when converting the value * the precision plays no role when converting the value
* @param mode the database mode * @param mode the database mode
* @param column the column that contains the ENUM datatype enumerators, * @param column the column (if any), used for to improve the error message if conversion fails
* @param enumerators the ENUM datatype enumerators (if any),
* for dealing with ENUM conversions * for dealing with ENUM conversions
* @return the converted value * @return the converted value
*/ */
@Override @Override
public Value convertTo(int t, int precision, Mode mode, Column column) { public Value convertTo(int t, int precision, Mode mode, Object column, String[] enumerators) {
if (t == type) { if (t == type) {
return this; return this;
} else if (t == Value.CLOB) { } else if (t == Value.CLOB) {
...@@ -514,7 +515,7 @@ public class ValueLob extends Value { ...@@ -514,7 +515,7 @@ public class ValueLob extends Value {
ValueLob copy = ValueLob.createBlob(getInputStream(), -1, handler); ValueLob copy = ValueLob.createBlob(getInputStream(), -1, handler);
return copy; return copy;
} }
return super.convertTo(t, precision, mode, column); return super.convertTo(t, precision, mode, column, null);
} }
@Override @Override
......
...@@ -14,6 +14,7 @@ import java.io.Reader; ...@@ -14,6 +14,7 @@ import java.io.Reader;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.SQLException; import java.sql.SQLException;
import org.h2.engine.Constants; import org.h2.engine.Constants;
import org.h2.engine.Mode; import org.h2.engine.Mode;
import org.h2.engine.SysProperties; import org.h2.engine.SysProperties;
...@@ -26,7 +27,6 @@ import org.h2.store.FileStoreOutputStream; ...@@ -26,7 +27,6 @@ import org.h2.store.FileStoreOutputStream;
import org.h2.store.LobStorageFrontend; import org.h2.store.LobStorageFrontend;
import org.h2.store.LobStorageInterface; import org.h2.store.LobStorageInterface;
import org.h2.store.fs.FileUtils; import org.h2.store.fs.FileUtils;
import org.h2.table.Column;
import org.h2.util.IOUtils; import org.h2.util.IOUtils;
import org.h2.util.MathUtils; import org.h2.util.MathUtils;
import org.h2.util.StringUtils; import org.h2.util.StringUtils;
...@@ -186,11 +186,13 @@ public class ValueLobDb extends Value implements Value.ValueClob, ...@@ -186,11 +186,13 @@ public class ValueLobDb extends Value implements Value.ValueClob,
* @param t the new type * @param t the new type
* @param precision the precision * @param precision the precision
* @param mode the mode * @param mode the mode
* @param column the column * @param column the column (if any), used for to improve the error message if conversion fails
* @param enumerators the ENUM datatype enumerators (if any),
* for dealing with ENUM conversions
* @return the converted value * @return the converted value
*/ */
@Override @Override
public Value convertTo(int t, int precision, Mode mode, Column column) { public Value convertTo(int t, int precision, Mode mode, Object column, String[] enumerators) {
if (t == type) { if (t == type) {
return this; return this;
} else if (t == Value.CLOB) { } else if (t == Value.CLOB) {
...@@ -210,7 +212,7 @@ public class ValueLobDb extends Value implements Value.ValueClob, ...@@ -210,7 +212,7 @@ public class ValueLobDb extends Value implements Value.ValueClob,
return ValueLobDb.createSmallLob(t, small); return ValueLobDb.createSmallLob(t, small);
} }
} }
return super.convertTo(t, precision, mode, column); return super.convertTo(t, precision, mode, column, null);
} }
@Override @Override
......
...@@ -13,9 +13,9 @@ import java.sql.PreparedStatement; ...@@ -13,9 +13,9 @@ import java.sql.PreparedStatement;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Time; import java.sql.Time;
import java.sql.Timestamp; import java.sql.Timestamp;
import org.h2.engine.Mode; import org.h2.engine.Mode;
import org.h2.message.DbException; import org.h2.message.DbException;
import org.h2.table.Column;
/** /**
* Implementation of NULL. NULL is not a regular data type. * Implementation of NULL. NULL is not a regular data type.
...@@ -133,7 +133,7 @@ public class ValueNull extends Value { ...@@ -133,7 +133,7 @@ public class ValueNull extends Value {
} }
@Override @Override
public Value convertTo(int type, int precision, Mode mode, Column column) { public Value convertTo(int type, int precision, Mode mode, Object column, String[] enumerators) {
return this; return this;
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论